
package com.jf.cloud.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.jf.cloud.api.auth.constant.SysTypeEnum;
import com.jf.cloud.api.combo.feign.ComboFeignClient;
import com.jf.cloud.api.coupon.feign.CouponFeignClient;
import com.jf.cloud.api.delivery.feign.DeliveryFeignClient;
import com.jf.cloud.api.delivery.feign.SameCityFeignClient;
import com.jf.cloud.api.delivery.vo.SameCityVO;
import com.jf.cloud.api.delivery.vo.ShopTransportVO;
import com.jf.cloud.api.discount.feign.DiscountFeignClient;
import com.jf.cloud.api.distribution.feign.DistributionFeignClient;
import com.jf.cloud.api.feign.SearchSpuFeignClient;
import com.jf.cloud.api.flow.feign.FlowFeignClient;
import com.jf.cloud.api.group.feign.GroupFeignClient;
import com.jf.cloud.api.group.vo.GroupActivityVO;
import com.jf.cloud.api.leaf.feign.SegmentFeignClient;
import com.jf.cloud.api.multishop.bo.EsShopDetailBO;
import com.jf.cloud.api.multishop.constant.ShopStatus;
import com.jf.cloud.api.multishop.feign.IndexImgFeignClient;
import com.jf.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.jf.cloud.api.multishop.feign.ShopSubstituteSalesFeignClient;
import com.jf.cloud.api.multishop.vo.ShopDetailVO;
import com.jf.cloud.api.platform.constant.OfflineHandleEventStatus;
import com.jf.cloud.api.platform.constant.OfflineHandleEventType;
import com.jf.cloud.api.platform.dto.OfflineHandleEventDTO;
import com.jf.cloud.api.platform.feign.ConfigFeignClient;
import com.jf.cloud.api.platform.feign.OfflineHandleEventFeignClient;
import com.jf.cloud.api.platform.vo.OfflineHandleEventVO;
import com.jf.cloud.api.product.bo.SpuSimpleBO;
import com.jf.cloud.api.product.util.ProductLangUtil;
import com.jf.cloud.api.seckill.feign.SeckillFeignClient;
import com.jf.cloud.api.seckill.vo.SeckillApiVO;
import com.jf.cloud.api.supplier.bo.SupplierDetailBO;
import com.jf.cloud.api.supplier.constant.SupplierStatus;
import com.jf.cloud.api.supplier.feign.SupplierDetailFeignClient;
import com.jf.cloud.api.supplier.vo.SupplierApiDetailVO;
import com.jf.cloud.api.vo.EsPageVO;
import com.jf.cloud.common.cache.constant.CacheNames;
import com.jf.cloud.common.cache.constant.ProductCacheNames;
import com.jf.cloud.common.cache.util.RedisUtil;
import com.jf.cloud.common.constant.Constant;
import com.jf.cloud.common.constant.DistributedIdKey;
import com.jf.cloud.common.constant.SendTypeEnum;
import com.jf.cloud.common.constant.StatusEnum;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.database.util.PageAdapter;
import com.jf.cloud.common.database.util.PageUtil;
import com.jf.cloud.common.database.vo.PageVO;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.i18n.I18nMessage;
import com.jf.cloud.common.i18n.LanguageEnum;
import com.jf.cloud.common.order.vo.SendNotifyBO;
import com.jf.cloud.common.product.bo.EsCategoryBO;
import com.jf.cloud.common.product.constant.*;
import com.jf.cloud.common.product.dto.*;
import com.jf.cloud.common.product.vo.*;
import com.jf.cloud.common.product.vo.app.SkuAppVO;
import com.jf.cloud.common.product.vo.app.SpuAppVO;
import com.jf.cloud.common.product.vo.search.SpuAdminVO;
import com.jf.cloud.common.product.vo.search.SpuSearchVO;
import com.jf.cloud.common.response.ResponseEnum;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.common.rocketmq.config.RocketMqConstant;
import com.jf.cloud.common.security.AuthUserContext;
import com.jf.cloud.common.util.Json;
import com.jf.cloud.common.util.PriceUtil;
import com.jf.cloud.common.vo.ShopSubstituteSalesVO;
import com.jf.cloud.product.dto.SpuPageSearchDTO;
import com.jf.cloud.product.mapper.*;
import com.jf.cloud.product.model.*;
import com.jf.cloud.product.service.*;
import com.jf.cloud.product.vo.SpuCountVO;
import com.jf.cloud.product.vo.SupplierSpuVo;
import io.seata.spring.annotation.GlobalTransactional;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * spu信息
 *
 * @author zz
 * @date 2020-10-28 15:27:24
 */
@Service
public class SpuServiceImpl implements SpuService {
    private final Logger logger = LoggerFactory.getLogger(SpuServiceImpl.class);

    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private SegmentFeignClient segmentFeignClient;
    @Autowired
    private SpuOfflineService spuOfflineService;
    @Autowired
    private SpuDetailService spuDetailService;
    @Autowired
    private SpuExtensionService spuExtensionService;
    @Autowired
    private SpuTagReferenceService spuTagReferenceService;
    @Autowired
    private SpuAttrValueService spuAttrValueService;
    @Autowired
    private MapperFacade mapperFacade;
    @Autowired
    private SkuService skuService;
    @Autowired
    private SpuLangService spuLangService;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private CategoryBrandService categoryBrandService;
    @Autowired
    private BrandMapper brandMapper;
    @Autowired
    private BrandShopService brandShopService;
    @Autowired
    private CategoryShopMapper categoryShopMapper;
    @Autowired
    private FlowFeignClient flowFeignClient;
    @Autowired
    private DiscountFeignClient discountFeignClient;
    @Autowired
    private CouponFeignClient couponFeignClient;
    @Autowired
    private OfflineHandleEventFeignClient offlineHandleEventFeignClient;
    @Autowired
    private GroupFeignClient groupFeignClient;

    @Autowired
    private SeckillFeignClient seckillFeignClient;
    @Autowired
    private ComboFeignClient comboFeignClient;
    @Autowired
    private SearchSpuFeignClient searchSpuFeignClient;
    @Autowired
    private ShopDetailFeignClient shopDetailFeignClient;
    @Autowired
    private DistributionFeignClient distributionFeignClient;
    @Autowired
    private DeliveryFeignClient deliveryFeignClient;
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private ShopSubstituteSalesFeignClient shopSubstituteSalesFeignClient;
    @Autowired
    private SupplierDetailFeignClient supplierDetailFeignClient;
    @Autowired
    private SkuLangService skuLangService;
    @Autowired
    private SpuConsignmentChangeMapper spuConsignmentChangeMapper;
    @Autowired
    private SpuSupplierChangeLogService spuSupplierChangeLogService;
    @Autowired
    private ImportSupplierSpuService importSupplierSpuService;
    @Autowired
    private SupplierSpuUpdateLaterOperateService supplierSpuUpdateLaterOperateService;
    @Autowired
    private GiveawaySpuMapper giveawaySpuMapper;
    @Autowired
    private RocketMQTemplate sendProductNotifyToShopTemplate;
    @Autowired
    private ConfigFeignClient configFeignClient;
    @Autowired
    private SkuStockService skuStockService;
    @Autowired
    private SameCityFeignClient sameCityFeignClient;
    @Autowired
    private IndexImgFeignClient indexImgFeignClient;

    @Autowired
    private GiveawayService giveawayService;

    @Autowired
    private SpuRankService spuRankService;

    @Override
    public PageVO<SpuVO> page(PageDTO pageDTO, SpuPageSearchDTO spuDTO) {
        PageVO<SpuVO> spuPage = PageUtil.doPage(pageDTO, () -> spuMapper.list(spuDTO));
        return spuPage;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SPU_KEY, key = "#spuId", sync = true)
    public SpuVO getBySpuId(Long spuId) {
        SpuVO spu = spuMapper.getBySpuId(spuId);
        if (Objects.isNull(spu)) {
            throw new LuckException(ResponseEnum.SPU_NOT_EXIST);
        }
        // 定金预售
        if (Objects.equals(spu.getPreSaleType(), PreSaleType.DEPOSIT.value())) {
            spu.setDepositValue(PriceUtil.toDecimalPrice(spu.getDepositAmount()));
            spu.setDepositExpansionValue(PriceUtil.toDecimalPrice(spu.getDepositExpansionAmount()));
        }
        return spu;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SPU_EXTENSION_KEY, key = "#spuId", sync = true)
    public SpuExtension getSpuExtension(Long spuId) {
        return spuExtensionService.getBySpuId(spuId);
    }

    @Override
    public void batchRemoveSpuActivityCache(List<Long> spuIds) {
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        RedisUtil.deleteBatch(CacheNames.SPU_ACTIVITY_KEY, spuIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void changeSpuStatus(Long spuId, Integer status) {
        batchChangeSpuStatus(Collections.singletonList(spuId), status);
//        spuMapper.changeSpuStatus(spuId, status);
//        if (Objects.equals(status, StatusEnum.DISABLE.value()) || Objects.equals(status, StatusEnum.OFFLINE.value())) {
//            // 删掉满减、优惠券的商品关联信息
//            handleSpuStatusChange(Collections.singletonList(spuId));
//            seckillFeignClient.offlineSeckillBySpuIds(Collections.singletonList(spuId));
//        }
    }

    @Override
    public void batchChangeSpuStatus(List<Long> spuIds, Integer status) {
        if (Objects.isNull(AuthUserContext.get().getSysType())) {
            throw new LuckException("下线异常");
        }
        spuMapper.batchChangeSpuStatus(spuIds, status);
        // 更新品牌信息
        List<Long> brandIds = brandMapper.listBrandIdBySpuIds(spuIds);
        brandMapper.batchUpdateSpuCount(brandIds);
        if (Objects.equals(status, StatusEnum.DISABLE.value()) || Objects.equals(status, StatusEnum.OFFLINE.value())) {
            // 更新商品分组信息
            handleStatusChange(spuIds);
            // T删掉满减、优惠券的商品关联信息
            if (!Objects.isNull(AuthUserContext.get())) {
                handleSpuStatusChange(spuIds);
            } else {
                handleCommissionSpuStatusChange(spuIds);
            }
            // 下线掉关联商品的活动 (在线下活动之前已经修改了商品的状态，下面的方法就查询不到已有的商品了，所以就需要带着修改后的商品去状态去查询)
            spuOfflineService.offlineSpuStatusAndActivity(1, spuIds, null, null, status, null);
        } else if (Objects.equals(status, StatusEnum.ENABLE.value())) {
            handleDistributionSpuStatusChange(spuIds, status);
        }
    }

    @Override
    public void batchChangeCommissionSpuStatus(List<Long> spuIds, Integer status, Integer sysType) {
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        spuMapper.batchChangeSpuStatus(spuIds, status);
        // 更新品牌信息
        List<Long> brandIds = brandMapper.listBrandIdBySpuIds(spuIds);
        brandMapper.batchUpdateSpuCount(brandIds);
        if (Objects.equals(status, StatusEnum.DISABLE.value()) || Objects.equals(status, StatusEnum.OFFLINE.value())) {
            // 更新商品分组信息
            handleStatusChange(spuIds);
            // T删掉满减、优惠券的商品关联信息
            if (!Objects.isNull(AuthUserContext.get())) {
                handleSpuStatusChange(spuIds);
            } else {
                handleCommissionSpuStatusChange(spuIds);
            }
            // 下线掉关联商品的活动 (在线下活动之前已经修改了商品的状态，下面的方法就查询不到已有的商品了，所以就需要带着修改后的商品去状态去查询)
            spuOfflineService.offlineCommissionSpuStatusAndActivity(1, spuIds, null, null, status, sysType);
        } else if (Objects.equals(status, StatusEnum.ENABLE.value())) {
            handleDistributionSpuStatusChange(spuIds, status);
        }
    }

    private void handleDistributionSpuStatusChange(List<Long> spuIds, Integer status) {
        List<Long> shopIds;
        if (Objects.equals(AuthUserContext.get().getTenantId(), Constant.PLATFORM_SHOP_ID)) {
            shopIds = new ArrayList<>();
        } else {
            shopIds = spuMapper.spuShopIdsBySpuIds(spuIds);
        }
        ServerResponseEntity<Void> responseEntity = distributionFeignClient.handleSpuState(spuIds, shopIds, status);
        if (responseEntity.isFail()) {
            throw new LuckException(responseEntity.getMsg());
        }
    }

    private void handleSpuStatusChange(List<Long> spuIds) {
        List<Long> shopIds;
        if (Objects.equals(AuthUserContext.get().getTenantId(), Constant.PLATFORM_SHOP_ID)) {
            shopIds = new ArrayList<>();
        } else {
            shopIds = spuMapper.spuShopIdsBySpuIds(spuIds);
        }
        if (CollUtil.isNotEmpty(spuIds)) {
            ServerResponseEntity<Void> discountResponseEntity = discountFeignClient.handleSpuOffline(spuIds, shopIds);
            if (discountResponseEntity.isFail()) {
                throw new LuckException(discountResponseEntity.getMsg());
            }
            ServerResponseEntity<Void> couponResponseEntity = couponFeignClient.handleSpuOffline(spuIds, shopIds);
            if (couponResponseEntity.isFail()) {
                throw new LuckException(couponResponseEntity.getMsg());
            }
        }
    }

    private void handleCommissionSpuStatusChange(List<Long> spuIds) {
        List<Long> shopIds = spuMapper.spuShopIdsBySpuIds(spuIds);
        if (CollUtil.isNotEmpty(spuIds)) {
            ServerResponseEntity<Void> discountResponseEntity = discountFeignClient.handleSpuOffline(spuIds, shopIds);
            if (discountResponseEntity.isFail()) {
                throw new LuckException(discountResponseEntity.getMsg());
            }
            ServerResponseEntity<Void> couponResponseEntity = couponFeignClient.handleSpuOffline(spuIds, shopIds);
            if (couponResponseEntity.isFail()) {
                throw new LuckException(couponResponseEntity.getMsg());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SpuDTO spuDTO) {
        int sysType = AuthUserContext.get().getSysType();
        if (sysType == SysTypeEnum.MULTISHOP.value()) {
            spuDTO.setShopId(AuthUserContext.get().getTenantId());
            spuDTO.setSupplierId(-1L);
        } else if (sysType == SysTypeEnum.SUPPLIER.value()) {
            spuDTO.setSupplierId(AuthUserContext.get().getTenantId());
            spuDTO.setShopId(-1L);
        }
        checkSaveOrUpdateInfo(spuDTO, true);
        Spu spu = mapperFacade.map(spuDTO, Spu.class);
        handlePreSaleInfo(spuDTO, spu);
        ServerResponseEntity<Long> segmentIdResponse = segmentFeignClient.getSegmentId(DistributedIdKey.MALL4CLOUD_SPU);
        if (!segmentIdResponse.isSuccess()) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
        Long spuId = segmentIdResponse.getData();
        spu.setSpuId(spuId);
        //判断发货方式，供应商发货属于代销商品
        if (Objects.nonNull(spu.getSupplierDeliveryType()) && Objects.equals(spu.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
            //供应商商品类型为代销商品
            spu.setSupplierSpuType(SupplierSpuType.CONSIGNMENT.value());
            //判断规格全选还是部分选择
            //获取供应商商品sku信息
            List<SkuVO> skuVOS = skuService.listSkuAllInfoBySpuId(spu.getSupplierSpuId(), false);
            //判断选择sku长度是否小于供应商商品sku
            spu.setSkuChoiceStatus(SkuChoiceStatus.ALL_CHOICE.value());
            if (spuDTO.getSkuList().size() < skuVOS.size()) {
                //规格部分选择
                spu.setSkuChoiceStatus(SkuChoiceStatus.PART_CHOICE.value());
            }
        }
        //判断发货方式，商家发货属于普通商品
        if (Objects.nonNull(spu.getSupplierDeliveryType()) && Objects.equals(spu.getSupplierDeliveryType(), SupplierDeliveryType.SHOP_DELIVERY.value())) {
            spu.setSupplierSpuType(SupplierSpuType.NO.value());
        }
        // 判断是否开启“商品发布审核”，若开启，商品状态改为“待审核”【平台端发布不用审核】
        String prodSwitchConfig = configFeignClient.getConfig(Constant.SPU_SWITCH_CONFIG).getData();
        if (!SysTypeEnum.PLATFORM.value().equals(sysType)
                && !ObjectUtils.isEmpty(prodSwitchConfig)) {
            Boolean spuAudit = JSON.parseObject(prodSwitchConfig, new TypeReference<Map<String, Boolean>>() {
            })
                    .getOrDefault("spuAudit", false);
            if (spuAudit) {
                spu.setStatus(SpuStatus.PUBLISH_WAIT_AUDIT.value());
            }
        }
        // 1.保存商品信息
        spu.setBrandId(Objects.equals(spuDTO.getBrandId(), 0L) ? null : spuDTO.getBrandId());
        spu.setScoreFee(Objects.isNull(spuDTO.getScoreFee()) ? Constant.ZERO_LONG : spuDTO.getScoreFee());
        if (!Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
            if (!Objects.isNull(spuDTO.getSupplierDeliveryType())) {
                spu.setDeliveryTemplateId(Objects.nonNull(spuDTO.getSupplierDeliveryType()) && spuDTO.getSupplierDeliveryType() == 2 ? spuDTO.getDeliveryTemplateId() : 0);
            }
        }
        spu.setSupplierId(Objects.isNull(spu.getSupplierId()) ? 0L : spu.getSupplierId());
        //供应商商品没有店铺分类
        spu.setShopCategoryId(Objects.equals(spu.getSupplierId(), -1L) ? spuDTO.getShopCategoryId() : -1L);
        spu.setSpuMold(Objects.nonNull(spuDTO.getSpuMold()) ? spuDTO.getSpuMold() : 0);
        if (Objects.equals(spu.getSpuMold(), 1)) {
            // 虚拟商品的配送方式
            SpuVO.DeliveryModeVO mode = new SpuVO.DeliveryModeVO();
            mode.setHasShopDelivery(true);
            mode.setHasUserPickUp(false);
            mode.setHasCityDelivery(false);
            spu.setDeliveryMode(Json.toJsonString(mode));
        }
        spu.setSkuZoned(0);
        spuMapper.save(spu);
        // 2.保存商品属性信息
        spuAttrValueService.save(spu.getSpuId(), spu.getCategoryId(), spuDTO.getSpuAttrValues(), AuthUserContext.get().getSysType());
        // 3.国际化信息、商品详情
        spuDTO.setSpuId(spu.getSpuId());
        loadSpuLangInfo(spuDTO, Boolean.TRUE);
        // 4.商品扩展信息
        SpuExtension spuExtension = new SpuExtension();
        spuExtension.setSpuId(spu.getSpuId());
        spuExtension.setActualStock(spuDTO.getTotalStock());
        spuExtension.setStock(spuDTO.getTotalStock());
        spuExtensionService.save(spuExtension);
        // 5.保存sku信息
        skuService.save(spu.getSpuId(), spuDTO.getSkuList(), AuthUserContext.get().getSysType(), AuthUserContext.get().getUserId(), AuthUserContext.get().getTenantId());
        // 6.更新品牌信息，仅在商家端发布商品时才更新
        if (Objects.equals(sysType, SysTypeEnum.MULTISHOP.value()) && Objects.nonNull(spu.getBrandId())) {
            brandMapper.batchUpdateSpuCount(Collections.singleton(spu.getBrandId()));
        }
        //7.如果是电影院类虚拟商品 需要存座位信息
        if (Objects.equals(spu.getSpuMold(), 1) && Objects.nonNull(spuDTO.getRank())) {
            saveSpuBrank(spuDTO.getRank(), spuId, AuthUserContext.get().getTenantId());
        }

    }

    /**
     * 处理电影院类座位
     */
    private void saveSpuBrank(List<RankDTO> list, Long spuId, Long shopId) {
        for (int r = 0; r < list.size(); r++) {
            RankDTO rankDTO = list.get(r);
            int skuId = rankDTO.getIndex();
            JSONArray array = JSONArray.parseArray(rankDTO.getHiddens());
            List<SpuRank> ls = new ArrayList<>();
            for (int i = 0; i < rankDTO.getRowCount(); i++) {
                for (int j = 0; j < rankDTO.getColCount(); j++) {
                    SpuRank spuRank = new SpuRank();
                    spuRank.setColCount(rankDTO.getColCount());
                    spuRank.setRowCount(rankDTO.getRowCount());
                    spuRank.setShopId(shopId);
                    spuRank.setSpuId(spuId);
                    spuRank.setRowNum(i + 1);
                    spuRank.setColNum(j + 1);
                    spuRank.setStatus(0);
                    spuRank.setXCoord(spuRank.getColNum()+9);
                    spuRank.setYCoord(spuRank.getRowNum()+2);
                    spuRank.setSkuId(skuId);
                    spuRank.setCreateTime(new Date());
                    ls.add(spuRank);

                }

            }

            for (int i = 0; i < ls.size(); i++) {
                SpuRank spuRank = ls.get(i);
                if (array.size() > 0) {
                    for (int k = 0; k < array.size(); k++) {
                        JSONObject rank = array.getJSONObject(k);
                        if (rank.getInteger("rowNum") == spuRank.getRowNum() && rank.getInteger("colNum") == spuRank.getColNum()) {
                            spuRank.setStatus(rank.getInteger("status"));
                            spuRank.setRowNum(rank.getInteger("rowNum"));
                            spuRank.setColNum(rank.getInteger("colNum"));
                            spuRank.setXCoord(rank.getInteger("xCoord"));
                            spuRank.setYCoord(rank.getInteger("yCoord"));
                        }
                    }
                }
                spuRankService.save(spuRank);
            }

        }

    }

    /**
     * 处理商品的预售信息
     *
     * @param spuDTO
     * @param spu
     */
    private void handlePreSaleInfo(SpuDTO spuDTO, Spu spu) {
        if (Objects.isNull(spuDTO.getPreSaleType()) || Objects.equals(spuDTO.getPreSaleType(), PreSaleType.DISABLE.value())) {
            spu.setPreSaleType(-1);
            return;
        }
        if (!(Objects.equals(spuDTO.getPreSaleType(), PreSaleType.FULLPAY.value()) || Objects.equals(spuDTO.getPreSaleType(), PreSaleType.DEPOSIT.value()))) {
            spu.setPreSaleType(-1);
            return;
        }
//        spu.setSpuType(SpuType.PRESALE.value());
        if (Objects.isNull(spuDTO.getPreSaleDeliveryType())) {
            throw new LuckException(ResponseEnum.DATA_INCOMPLETE);
        }
        // 定金预售
        if (Objects.equals(spuDTO.getPreSaleType(), PreSaleType.DEPOSIT.value())) {
            Long depositAmount = PriceUtil.toLongCent(spuDTO.getDepositValue());
            if (depositAmount < 1) {
                throw new LuckException("定金数值设置错误，数值不能小于0.01");
            }
            spu.setDepositAmount(depositAmount);
            Long depositExpansionAmount = PriceUtil.toLongCent(spuDTO.getDepositExpansionValue());
            long balanceAmount = spu.getPriceFee() - depositExpansionAmount;
            if (depositExpansionAmount < 1) {
                throw new LuckException("定金膨胀数值设置错误，数值不能小于0.01");
            }
            if (depositExpansionAmount < depositAmount) {
                spu.setDepositExpansionAmount(depositAmount);
            }
            if (Objects.equals(spuDTO.getDepositType(), 1) && balanceAmount < 0) {
                throw new LuckException("定金膨胀数值不能大于最低尾款数值");
            }
            spu.setDepositExpansionAmount(depositExpansionAmount);
            // 校验时间先后顺序
            if (spuDTO.getBalanceStartTime().getTime() < spuDTO.getDepositStartTime().getTime() || spuDTO.getBalanceEndTime().getTime() < spuDTO.getDepositEndTime().getTime()) {
                throw new LuckException(ResponseEnum.HTTP_MESSAGE_NOT_READABLE);
            }
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SPU_KEY, key = "#spuDTO.spuId")
    @Transactional(rollbackFor = Exception.class)
    public void update(SpuDTO spuDTO) {
        Integer sysType = AuthUserContext.get().getSysType();
        checkSaveOrUpdateInfo(spuDTO, false);
        Spu spu = mapperFacade.map(spuDTO, Spu.class);
        SpuVO spuDb = spuMapper.getBySpuId(spu.getSpuId());
        handlePreSaleInfo(spuDTO, spu);
        if (Objects.nonNull(spuDTO.getPreSaleType()) && !Objects.equals(spuDTO.getPreSaleType(), PreSaleType.DISABLE.value())) {
            checkProductType(spuDb);
        }
        spu.setBrandId(Objects.isNull(spuDTO.getBrandId()) ? Constant.ZERO_LONG : spuDTO.getBrandId());
        //代销商品验证基本信息是否更改
        if (Objects.equals(spuDTO.getSupplierSpuType(), SupplierSpuType.CONSIGNMENT.value())) {
            verifySpuMsgIsChange(spuDTO);
        }
        // 如果是虚拟商品，在保存一下默认配送json
        if (Objects.equals(spu.getSpuMold(), 1)) {
            // 虚拟商品的配送方式
            SpuVO.DeliveryModeVO mode = new SpuVO.DeliveryModeVO();
            mode.setHasShopDelivery(true);
            mode.setHasUserPickUp(false);
            mode.setHasCityDelivery(false);
            spu.setDeliveryMode(Json.toJsonString(mode));
        }
        // 1.修改商品信息
        spuMapper.update(spu);
        // 2.非代销商品修改属性信息
        if (!Objects.equals(spu.getSupplierSpuType(), SupplierSpuType.CONSIGNMENT.value())) {
            spuAttrValueService.update(spu.getSpuId(), spu.getCategoryId(), spuDb.getSupplierSpuType(), spuDTO.getSpuAttrValues());
        }
        // 3.国际化信息、商品详情
        loadSpuLangInfo(spuDTO, Boolean.FALSE);
        String s = "{hasUserPickUp':false,'hasCityDelivery':false,'hasShopDelivery':true}";
        //校验赠品活动
        giveawayService.checkGiveawaySpuPrice(spuDTO);
        // 更新商品库存及sku信息
        updateSku(spuDTO);

        // 更新品牌信息
        if (!Objects.equals(spuDb.getBrandId(), spu.getBrandId())) {
            List<Long> brandIds = new ArrayList<>();
            brandIds.add(spuDb.getBrandId());
            brandIds.add(spu.getBrandId());
            brandMapper.batchUpdateSpuCount(brandIds);
        }
        if (Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
            //供应商修改 商家供应商发货的商品时
            //给代销商品增加供应商是商品更新标识
            List<SpuVO> commissionSpuList = spuMapper.getCommissionSpuListBySupplierDeliver(spuDb.getSpuId());
            SendStatus sendStatus = sendProductNotifyToShopTemplate.syncSend(RocketMqConstant.SUPPLIER_PRODUCT_UPDATE, new GenericMessage<Long>(spu.getSpuId())).getSendStatus();
            if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
//            List<Long> spuIdList = commissionSpuList.stream().map(e -> e.getSpuId()).collect(Collectors.toList());
//            if(CollUtil.isNotEmpty(spuIdList)){
//                spuMapper.batchChangeSynUpdate(spuIdList,IsSynUpdate.NO_CHANGE.value());
//            }
            ServerResponseEntity<SupplierDetailBO> supplierResp = supplierDetailFeignClient.getSupplierBySupplierId(spuDb.getSupplierId());
            //发送给商家 代销商品变更提醒
            //批量发送商品下架消息给商家或供应商：商品xxx已被平台或供应商下架，点击去查看
            List<SendNotifyBO> notifyList = new ArrayList<>();
            for (SpuVO spuVO : commissionSpuList) {
                SendNotifyBO sendNotifyBO = new SendNotifyBO();
                sendNotifyBO.setShopId(spuVO.getShopId());
                sendNotifyBO.setSendType(SendTypeEnum.COMMISSION_CHANGE.getValue());
                sendNotifyBO.setSpuId(spuVO.getSpuId());
                sendNotifyBO.setSpuName(spuVO.getName());
                sendNotifyBO.setSupplierName(supplierResp.getData().getSupplierName());
                notifyList.add(sendNotifyBO);
            }
            SendStatus sendStockStatus = sendProductNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_PRODUCT_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(notifyList)).getSendStatus();
            if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        }
        //改变 供应商商品更新后代销商品是否已同步更新
        if (!Objects.isNull(spuDTO.getIsSynUpdate()) && Objects.equals(spuDTO.getIsSynUpdate(), IsSynUpdate.NO_CHANGE.value)) {
            spuMapper.changeSynUpdate(spuDTO.getSpuId(), IsSynUpdate.YEW_CHANGE.value());
        }
        // 移除代销商品基本信息是否改变缓存
        RedisUtil.del(CacheNames.SPU_SUPPLIER_CHANGE_LOG + CacheNames.UNION + spuDTO.getSpuId());
    }

    /**
     * 检查商品活动是否冲突
     *
     * @param spuDb 修改前的商品信息
     */
    private void checkProductType(SpuVO spuDb) {
        // 拼团商品
        if (Objects.equals(spuDb.getSpuType(), SpuType.GROUP.value()) && Objects.nonNull(spuDb.getActivityId()) && !Objects.equals(spuDb.getActivityId(), 0)) {
            ServerResponseEntity<GroupActivityVO> activityInfo = groupFeignClient.getActivityInfo(spuDb.getActivityId());
            String activityName = "";
            if (activityInfo.isSuccess()) {
                activityName = activityInfo.getData().getActivityName();
            }
            throw new LuckException("商品已经参加名为" + activityName + "的拼团活动,活动失效或结束后才能修改预售信息");
        }
        // 秒杀商品
        if (Objects.equals(spuDb.getSpuType(), SpuType.SECKILL.value()) && Objects.nonNull(spuDb.getActivityId()) && !Objects.equals(spuDb.getActivityId(), 0)) {
            ServerResponseEntity<SeckillApiVO> seckillInfo = seckillFeignClient.getSeckillInfoById(spuDb.getActivityId());
            String seckillName = "";
            if (seckillInfo.isSuccess()) {
                seckillName = seckillInfo.getData().getSeckillName();
            }
            throw new LuckException("商品已经参加名为" + seckillName + "的秒杀活动,活动失效或结束后才能修改预售信息");
        }
        // 积分商品
        if (Objects.equals(spuDb.getSpuType(), SpuType.SCORE.value())) {
            throw new LuckException("积分商品无法参与预售活动");
        }
        // 活动商品
        if (Objects.equals(spuDb.getSpuType(), SpuType.ACTIVE.value())) {
            throw new LuckException("活动商品无法参与预售活动");
        }
        ServerResponseEntity<List<ComboVO>> comboInfoResponseEntity = comboFeignClient.listComboInfoBySpuId(spuDb.getShopId(), spuDb.getSpuId());
        List<ComboVO> comboVOList = comboInfoResponseEntity.getData();
        // 优惠套餐
        if (CollUtil.isNotEmpty(comboVOList)) {
            StringBuilder comboName = new StringBuilder("");
            comboVOList.forEach(comboVO -> comboName.append(comboVO.getName()).append(" "));
            throw new LuckException("此商品正在参加" + comboName + "优惠套餐,待套餐活动失效或结束后才能修改预售信息");
        }
    }

    private void verifySpuMsgIsChange(SpuDTO spuDTO) {
        SpuConsignmentChange spuConsignmentChange = new SpuConsignmentChange();
        spuConsignmentChange.setSpuId(spuDTO.getSpuId());
        spuConsignmentChange.setImageChange(spuDTO.getImageChange());
        spuConsignmentChange.setBrandChange(spuDTO.getBrandChange());
        spuConsignmentChange.setDetailChange(spuDTO.getDetailChange());
        spuConsignmentChange.setVideoChange(spuDTO.getVideoChange());
        spuConsignmentChange.setMeasureUnitChange(spuDTO.getMeasureUnitChange());
        spuConsignmentChange.setSellingPointChange(spuDTO.getSellingPointChange());
        spuConsignmentChange.setNameChange(spuDTO.getNameChange());
        spuConsignmentChange.setSpuCodeChange(spuDTO.getSpuCodeChange());
        if (Objects.isNull(spuDTO.getImageChange()) && Objects.isNull(spuDTO.getBrandChange()) && Objects.isNull(spuDTO.getDetailChange())
                && Objects.isNull(spuDTO.getVideoChange()) && Objects.isNull(spuDTO.getMeasureUnitChange())
                && Objects.isNull(spuDTO.getSellingPointChange()) && Objects.isNull(spuDTO.getNameChange()) && Objects.isNull(spuDTO.getSpuCodeChange())) {
            return;
        }
        spuConsignmentChangeMapper.updateBySpuId(spuConsignmentChange);
    }

    /**
     * @param
     */
    public void loadSpuLangInfo(SpuDTO spuDTO, Boolean isSave) {
        List<SpuDetail> spuDetailList = new ArrayList<>();
        List<SpuLang> spuLangList = new ArrayList<>();
        boolean dataCorrect = false;
        for (SpuLangDTO spuLangDTO : spuDTO.getSpuLangList()) {
            SpuLang spuLang = mapperFacade.map(spuLangDTO, SpuLang.class);
            spuLang.setSpuId(spuDTO.getSpuId());
            boolean isBlank = StrUtil.isBlank(spuLang.getSpuName()) && StrUtil.isBlank(spuLang.getSellingPoint());
            if (!isBlank) {
                spuLangList.add(spuLang);
            }
            if (StrUtil.isNotBlank(spuLangDTO.getDetail())) {
                SpuDetail spuDetail = new SpuDetail();
                spuDetail.setSpuId(spuDTO.getSpuId());
                spuDetail.setLang(spuLangDTO.getLang());
                spuDetail.setDetail(spuLangDTO.getDetail());
                spuDetailList.add(spuDetail);
            }
            if (!isBlank && Objects.equals(spuLang.getLang(), Constant.DEFAULT_LANG)) {
                dataCorrect = true;
            }

        }

        // 商品名称、卖点，商品详情，是否包含默认语言信息
        if (CollUtil.isEmpty(spuLangList) || !dataCorrect) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }
        if (isSave) {
            if (spuDetailList.size() != 0) {
                spuDetailService.batchSave(spuDetailList);
            }
            if (spuLangList.size() != 0) {
                spuLangService.batchSave(spuLangList);
            }
            return;
        }
        SpuVO spuDb = getBySpuId(spuDTO.getSpuId());
        spuDetailService.update(spuDetailList, spuDb.getDetailList(), spuDb.getSpuId());
        spuLangService.update(spuLangList, spuDb.getSpuId());
    }


    /**
     * 更新sku列表信息
     *
     * @param spuDTO 商品信息
     */
    private void updateSku(SpuDTO spuDTO) {
        // 套餐,赠品商品禁止修改新增/删除/禁用sku
        List<SkuDTO> newSkuList = spuDTO.getSkuList();
        List<Integer> newSkuStatus = newSkuList.stream().map(SkuDTO::getStatus).collect(Collectors.toList());
        // 获取修改前的sku信息
        List<SkuVO> oldSkuList = skuService.listSkuWithAttrBySpuId(spuDTO.getSpuId());
        List<Integer> oldSkuStatus = oldSkuList.stream().map(SkuVO::getStatus).collect(Collectors.toList());
        boolean equals = newSkuStatus.equals(oldSkuStatus);
        if (newSkuList.size() != oldSkuList.size() || !equals) {
            Boolean isComboSpu = comboFeignClient.checkComboSpu(spuDTO.getSpuId(), spuDTO.getShopId()).getData();
            if (isComboSpu) {
                throw new LuckException("商品正在参与套餐活动，不能修改规格");
            }
            List<GiveawaySpuVO> giveawaySpuVOS = giveawaySpuMapper.getBySpuId(spuDTO.getSpuId());
            if (CollectionUtil.isNotEmpty(giveawaySpuVOS)) {
                throw new LuckException("商品正在参与赠品活动，不能修改规格");
            }
        }
        boolean notAllChange = false;
        Integer stock = 0;
        for (SkuDTO skuDTO : spuDTO.getSkuList()) {
            stock = Objects.isNull(skuDTO.getStock()) ? 0 : skuDTO.getStock() + stock;
            if (!notAllChange && Objects.nonNull(skuDTO.getSkuId())) {
                notAllChange = true;
            }
            if (Objects.isNull(skuDTO.getSkuId())) {
                if (spuDTO.getSpuType() != null && spuDTO.getSpuType().equals(SpuType.GROUP.value())) {
                    // 商品正在参与拼团活动，无法新增规格
                    throw new LuckException("商品正在参与拼团活动，无法新增规格");
                }
                if (spuDTO.getSpuType() != null && spuDTO.getSpuType().equals(SpuType.SECKILL.value())) {
                    // 商品正在参与秒杀活动，无法新增规格
                    throw new LuckException("商品正在参与秒杀活动，无法新增规格");
                }
            }
        }
        // 商品库存、商品sku
        SpuExtension spuExtension = new SpuExtension();
        spuExtension.setSpuId(spuDTO.getSpuId());
        // sku更新
        if (notAllChange) {
            skuService.update(spuDTO.getSpuId(), spuDTO.getSkuList());
            spuExtensionService.updateStock(spuDTO.getSpuId());
            updateGroupActivityPrice(spuDTO);
            return;
        }
        List<SkuVO> skuVOS = skuMapper.listSkuWithAttrBySpuId(spuDTO.getSpuId());
        if (skuVOS.size() > spuDTO.getSkuList().size()) {
            //删除了sku
            RedisUtil.set(ProductCacheNames.SKU_STATUS_DELETE + spuDTO.getSpuId(), 1, 2000);
            List<Long> commissionSpuIdList = spuMapper.getCommissionSpuIdList(spuDTO.getSpuId(), null);
            //改变 供应商商品更新后代销商品是否已同步更新
            if (commissionSpuIdList.size() != 0) {
                spuMapper.batchChangeSynUpdate(commissionSpuIdList, IsSynUpdate.YEW_CHANGE.value());
            }
        }
        // sku全部发生改变，删掉旧的数据，然后保存新的数据
        spuExtension.setStock(stock);
        spuExtension.setActualStock(stock);
        spuExtension.setLockStock(0);
        spuExtensionService.update(spuExtension);
        skuService.deleteBySpuId(spuDTO.getSpuId());
        skuService.save(spuDTO.getSpuId(), spuDTO.getSkuList(), AuthUserContext.get().getSysType(), AuthUserContext.get().getUserId(), AuthUserContext.get().getTenantId());
    }

    private void updateGroupActivityPrice(SpuDTO spuDTO) {
        List<Long> skuIds = spuDTO.getSkuList().stream().filter(sku -> Objects.equals(sku.getStatus(), 1)).map(SkuDTO::getSkuId).collect(Collectors.toList());
        ServerResponseEntity<Void> updateGroupActivityPrice = groupFeignClient.updateGroupActivityPrice(skuIds, spuDTO.getSpuId());
        if (updateGroupActivityPrice.isFail()) {
            throw new LuckException(updateGroupActivityPrice.getMsg());
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SPU_KEY, key = "#spuId")
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void deleteById(Long spuId) {
        SpuVO spuVO = getBySpuId(spuId);
        if (Objects.isNull(spuVO) || Objects.equals(spuVO.getStatus(), StatusEnum.DELETE.value())) {
            throw new LuckException("商品不存在或者已被删除！");
        }
        // 删除商品、sku信息(逻辑删除)
        spuMapper.updateStatusBySpuId(spuId);
        List<Long> spuIds = Collections.singletonList(spuId);
        // 删除关联活动的信息
        handleSpuStatusChange(spuIds);
        // 下线掉关联商品的活动 (在线下活动之前已经修改了商品的状态，下面的方法就查询不到已有的商品了，所以就需要带着修改后的商品去状态去查询)
        spuOfflineService.offlineSpuStatusAndActivity(1, spuIds, null, null, SpuStatus.DELETE.value(), null);
        // 更新品牌信息
        brandMapper.batchUpdateSpuCount(Collections.singleton(spuVO.getBrandId()));
        // 移除关联的分组
        handleStatusChange(Collections.singletonList(spuId));
        // 清除商品的统计数据
        flowFeignClient.deleteSpuDataBySpuId(spuId);
        //如果是供应商品,给代销商品标注供应商品以更新
        if (Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value())) {
            SpuDTO spuDTO = mapperFacade.map(spuVO, SpuDTO.class);
            offSupplierSendCommissionSpu(spuDTO);
            // 更新关联该商品的轮播图，以及缓存
            indexImgFeignClient.udpateIndexImgBySpuId(spuId, spuVO.getShopId());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSpuOrSku(SpuDTO spuDTO) {
        Spu spu = new Spu();
        spu.setSpuId(spuDTO.getSpuId());
        SpuVO spuDb = spuMapper.getBySpuId(spuDTO.getSpuId());
        List<SkuVO> skusDb = skuMapper.listSkuWithAttrBySpuId(spuDTO.getSpuId());
        // 修改商品名
        if (CollUtil.isNotEmpty(spuDTO.getSpuLangList())) {
            SpuVO spuVO = spuMapper.getBySpuId(spuDTO.getSpuId());
            if (Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.CONSIGNMENT.value())) {
                //代销商品修改名称，记录代销商品基本信息是否已更新
                SpuConsignmentChange spuConsignmentChange = new SpuConsignmentChange();
                spuConsignmentChange.setSpuId(spuDTO.getSpuId());
                spuConsignmentChange.setNameChange(1);
                spuConsignmentChangeMapper.updateBySpuId(spuConsignmentChange);
            }
            for (SpuLangDTO spuLangDTO : spuDTO.getSpuLangList()) {
                spuLangDTO.setSpuId(spuDTO.getSpuId());
            }
            spuLangService.update(mapperFacade.mapAsList(spuDTO.getSpuLangList(), SpuLang.class), spuDTO.getSpuId());
        }
        spu.setSeq(spuDTO.getSeq());
        if (CollUtil.isNotEmpty(spuDTO.getSkuList())) {
            skuService.updateAmountOrStock(spuDTO);
            spuExtensionService.updateStock(spuDTO.getSpuId());
        }
        spu.setPriceFee(spuDTO.getPriceFee());
        //校验赠品活动
        spuDTO.setPriceFee(null == spuDTO.getPriceFee() ? spuDb.getPriceFee() : spuDTO.getPriceFee());
        giveawayService.checkGiveawaySpuPrice(spuDTO);
        spuMapper.update(spu);
        //供应商修改spu信息时，生成对应的变更记录
        if (Objects.equals(AuthUserContext.get().getSysType(), SysTypeEnum.SUPPLIER.value())) {
            //变更类型 1.商品上架 2.商品下架 3.代销sku信息变更4.新增sku
            //新增sku
            List<SpuSupplierChangeLog> spuSupplierChangeLogs = new ArrayList<>();
            if (CollUtil.isNotEmpty(spuDTO.getSkuList()) && spuDTO.getSkuList().size() > skusDb.size()) {
                SpuSupplierChangeLog spuSupplierChangeLog = new SpuSupplierChangeLog();
                spuSupplierChangeLog.setSpuId(spuDTO.getSpuId());
                spuSupplierChangeLog.setChangeType(SupplierSpuChangeType.ADD_SKU.value());
                spuSupplierChangeLogs.add(spuSupplierChangeLog);
            }
            //商品上架
            if (!Objects.equals(spuDTO.getStatus(), spuDb.getStatus()) && Objects.equals(spuDTO.getStatus(), StatusEnum.ENABLE.value())) {
                SpuSupplierChangeLog spuSupplierChangeLog = new SpuSupplierChangeLog();
                spuSupplierChangeLog.setSpuId(spuDTO.getSpuId());
                spuSupplierChangeLog.setChangeType(SupplierSpuChangeType.PUT_SHELF.value());
                spuSupplierChangeLogs.add(spuSupplierChangeLog);
            }
            //商品下架
            if (!Objects.equals(spuDTO.getStatus(), spuDb.getStatus()) && Objects.equals(spuDTO.getStatus(), StatusEnum.DISABLE.value())) {
                SpuSupplierChangeLog spuSupplierChangeLog = new SpuSupplierChangeLog();
                spuSupplierChangeLog.setChangeType(SupplierSpuChangeType.OFF_SHELF.value());
                spuSupplierChangeLog.setSpuId(spuDTO.getSpuId());
                spuSupplierChangeLogs.add(spuSupplierChangeLog);
            }
            //代销商品信息变更
            if (Objects.equals(spuDb.getSupplierSpuType(), SupplierSpuType.YES.value())) {
                SpuSupplierChangeLog spuSupplierChangeLog = new SpuSupplierChangeLog();
                spuSupplierChangeLog.setChangeType(SupplierSpuChangeType.SKU_MSG_CHANGE.value());
                spuSupplierChangeLog.setSpuId(spuDTO.getSpuId());
                spuSupplierChangeLogs.add(spuSupplierChangeLog);
            }
            if (Objects.nonNull(spuSupplierChangeLogs) && spuSupplierChangeLogs.size() > 0) {
                spuSupplierChangeLogService.saveBatch(spuSupplierChangeLogs);
            }
//            //供应商修改供应商发货的商品时
//            //给代销商品增加供应商是商品更新标识
//            List<SpuVO> commissionSpuList = spuMapper.getCommissionSpuList(spuDb.getSpuId());
//            List<Long> spuIdList = commissionSpuList.stream().map(e -> e.getSpuId()).collect(Collectors.toList());
//            if(CollUtil.isNotEmpty(spuIdList)){
//                spuMapper.batchChangeSynUpdate(spuIdList,IsSynUpdate.NO_CHANGE.value());
//            }
//            //下架商家代销设置为手动设价代销商品
//            List<SpuVO> commissionSpuLists = spuMapper.getCommissionSpuLists(spuDTO.getSpuId());
//            offSupplierSendCommissionSpu(spuDTO);

        }
    }

    @Override
    public void updateSpuUpdateTime(List<Long> spuIds, List<Long> categoryIds, List<Long> shopIds, Integer sysType) {
        if (CollUtil.isEmpty(spuIds) && CollUtil.isEmpty(categoryIds) && CollUtil.isEmpty(shopIds)) {
            return;
        }
        spuMapper.updateSpuUpdateTime(spuIds, categoryIds, shopIds, sysType);
    }


    /**
     * 处理分类数据
     *
     * @param category
     * @return
     */
    private EsCategoryBO handleCategory(CategoryVO category) {
        EsCategoryBO categoryBO = new EsCategoryBO();
        categoryBO.setCategoryId(category.getCategoryId());
        Map<Integer, String> categoryMap = category.getCategoryLangList().stream().collect(Collectors.toMap(CategoryLangVO::getLang, CategoryLangVO::getName));
        categoryBO.setCategoryNameZh(categoryMap.get(LanguageEnum.LANGUAGE_ZH_CN.getLang()));
        categoryBO.setCategoryNameEn(categoryMap.get(LanguageEnum.LANGUAGE_EN.getLang()));
        return categoryBO;
    }

    @Override
    public List<Long> getSpuIdsBySpuUpdateDTO(List<Long> shopCategoryIds, List<Long> categoryIds, Long brandId, Long shopId) {
        if (CollUtil.isEmpty(shopCategoryIds) && CollUtil.isEmpty(categoryIds) && Objects.isNull(brandId) && Objects.isNull(shopId)) {
            return new ArrayList<>();
        }
        return spuMapper.getSpuIdsBySpuUpdateDTO(shopCategoryIds, categoryIds, brandId, shopId);
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SPU_ACTIVITY_KEY, key = "#spuId", sync = true)
    public SpuActivityAppVO spuActivityBySpuId(Long shopId, Long spuId) {
        SpuActivityAppVO spuActivity = new SpuActivityAppVO();
        // 满减活动
        ServerResponseEntity<List<SpuDiscountAppVO>> discountResponse = discountFeignClient.spuDiscountList(shopId, spuId);
        if (!Objects.equals(discountResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(discountResponse.getMsg());
        }
        spuActivity.setDiscountList(discountResponse.getData());

        // 优惠券
        ServerResponseEntity<List<SpuCouponAppVO>> couponResponse = couponFeignClient.couponOfSpuDetail(shopId, spuId);
        if (!Objects.equals(couponResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(couponResponse.getMsg());
        }
        spuActivity.setCouponList(couponResponse.getData());
        return spuActivity;
    }

    @Override
    public List<Long> listSpuIdsByShopId(Long shopId) {
        return spuMapper.getSpuIdsBySpuUpdateDTO(null, null, null, shopId);
    }

    @Override
    public SpuCountVO getSpuCountBySupplierId(Long supplierId) {
        return spuMapper.getSpuCountBySupplierId(supplierId);
    }

    //    @Override
//    public List<Long> listSpuIdsByShopIdAndStatus(Long shopId, Integer status) {
//        return spuMapper.listSpuIdByShopIdsAndStatus(Collections.singletonList(shopId), status);
//    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offlineSpuByShopId(Long shopId) {
        spuMapper.offlineSpuByShopId(shopId);
        // 查询出秒杀or团购的商品进行下线
        // 下线掉关联商品的活动
        // 下面这个方法查不到正常状态的商品了，所以需要把修改后的商品状态传过去
        spuOfflineService.offlineSpuStatusAndActivity(3, null, shopId, null, StatusEnum.DISABLE.value(), null);
    }

    @Override
    public List<SpuVO> list(SpuPageSearchDTO spu) {
        return spuMapper.list(spu);
    }

    @Override
    public void updateSpu(Spu spu) {
        spuMapper.update(spu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void offline(OfflineHandleEventDTO offlineHandleEventDto) {
        OfflineHandleEventDTO offlineHandleEvent = new OfflineHandleEventDTO();
        offlineHandleEvent.setHandleId(offlineHandleEventDto.getHandleId());
        offlineHandleEvent.setHandleType(OfflineHandleEventType.PROD.getValue());
        offlineHandleEvent.setOfflineReason(offlineHandleEventDto.getOfflineReason());
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.save(offlineHandleEvent);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        // 更新活动状态为下线状态
        changeSpuStatus(offlineHandleEvent.getHandleId(), StatusEnum.OFFLINE.value());
    }

    @Override
    public OfflineHandleEventVO getOfflineHandleEvent(Long couponId) {
        ServerResponseEntity<OfflineHandleEventVO> offlineHandleEventResponse =
                offlineHandleEventFeignClient.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.PROD.getValue(), couponId, null);
        return offlineHandleEventResponse.getData();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void audit(OfflineHandleEventDTO offlineHandleEventDto) {
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.auditOfflineEvent(offlineHandleEventDto);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        Long spuId = offlineHandleEventDto.getHandleId();
        // 审核通过
        if (Objects.equals(offlineHandleEventDto.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            changeSpuStatus(spuId, StatusEnum.DISABLE.value());
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventDto.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            changeSpuStatus(spuId, StatusEnum.OFFLINE.value());
        }
        //发送商品审核结果消息给商家或供应商：商品xxx审核成功，点击去查看
        SpuVO spuVO = spuMapper.getBySpuId(spuId);
        SendNotifyBO sendNotifyBO = new SendNotifyBO();
        if (Objects.nonNull(spuVO.getSupplierSpuType()) && Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value())) {
            sendNotifyBO.setShopId(spuVO.getSupplierId());
        } else {
            sendNotifyBO.setShopId(spuVO.getShopId());
        }
        sendNotifyBO.setSendType(Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value()) ? SendTypeEnum.PRODUCT_AUDIT_TO_SUPPLIER.getValue() : SendTypeEnum.PRODUCT_AUDIT.getValue());
        sendNotifyBO.setSpuId(spuVO.getSpuId());
        sendNotifyBO.setSpuName(spuVO.getName());

        SendStatus sendStockStatus = sendProductNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_PRODUCT_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(Collections.singletonList(sendNotifyBO))).getSendStatus();
        if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void auditApply(OfflineHandleEventDTO offlineHandleEventDto) {
        // 更新事件状态
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.updateToApply(offlineHandleEventDto);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        // 更新优惠券为待审核状态
        changeSpuStatus(offlineHandleEventDto.getHandleId(), StatusEnum.WAIT_AUDIT.value());
    }

    @Override
    public List<SpuVO> listCanSeckillProd(Long spuId, Long shopId) {
        PageDTO pageDTO = new PageDTO();
        pageDTO.setPageNum(0);
        pageDTO.setPageSize(PageDTO.MAX_PAGE_SIZE);
        SpuDTO spuDTO = new SpuDTO();
        spuDTO.setShopId(shopId);
        spuDTO.setSpuId(spuId);
        return spuMapper.listCanSeckillProd(new PageAdapter(pageDTO), spuDTO, I18nMessage.getLang());
    }

//    @Override
//    public PageVO<SpuVO> pageCanSeckillProd(PageDTO pageDTO, SpuDTO spuDTO) {
////        return PageUtil.doPage(pageDTO, () -> spuMapper.listCanSeckillProd(spuDTO));
//        PageVO<SpuVO> pageVO = new PageVO<>();
//        pageVO.setList(spuMapper.listCanSeckillProd(new PageAdapter(pageDTO), spuDTO));
//        pageVO.setTotal(spuMapper.countCanSeckillProd(spuDTO));
//        return pageVO;
//    }

    @Override
    public Integer countByTransportId(Long transportId) {

        return spuMapper.countByTransportId(transportId);
    }

    @Override
    public void changeToNormalSpu(List<Long> spuIds) {
        spuMapper.changeToNormalSpu(spuIds);
    }

    @Override
    public int countByCategoryAndShopId(Long categoryId, Long shopId, Integer sysType) {
        return spuMapper.countByCategoryAndShopId(categoryId, shopId, sysType);
    }

    @Override
    public void handleStatusChange(List<Long> spuIds) {
        // 删除商品的分组信息
        spuTagReferenceService.deleteSpuData(spuIds);

    }

    @Override
    public Integer countByUserId(Long userId) {
        return spuMapper.countByUserId(userId);
    }

    @Override
    public List<SpuVO> listSpuNameBySpuIds(List<Long> spuIds) {
        if (CollUtil.isEmpty(spuIds)) {
            return new ArrayList<>();
        }
        List<SpuVO> spuVOList = spuMapper.listSpuNameBySpuIds(spuIds);
        ProductLangUtil.spuList(spuVOList);
        return spuVOList;
    }

    @Override
    public List<SpuVO> listSpuDetailBySpuIds(List<Long> spuIds) {
        return spuMapper.listSpuDetailBySpuIds(spuIds);
    }

    @Override
    public void batchChangeSpuStatusByCidListAndShopId(List<Long> cidList, Integer status, Long shopId, Integer sysType) {
        if (Objects.isNull(cidList) || cidList.size() == 0) {
            return;
        }
        List<Long> spuIds = spuMapper.listIdByCidAndShopId(cidList, shopId, sysType);
        if (Objects.isNull(spuIds) || spuIds.size() == 0) {
            return;
        }
        this.batchChangeSpuStatus(spuIds, status);
    }

    @Override
    public List<SpuVO> listSpuBySpuIds(List<Long> spuIds) {
        if (CollUtil.isEmpty(spuIds)) {
            return null;
        }
        List<SpuVO> spuList = spuMapper.listSpuBySpuIds(spuIds);
        ProductLangUtil.spuList(spuList);
        if (CollectionUtil.isEmpty(spuList)) {
            return spuList;
        }
        List<Long> shopIds = spuList.stream().map(SpuVO::getShopId).collect(Collectors.toList());
        ServerResponseEntity<List<ShopDetailVO>> shopResponse = shopDetailFeignClient.listByShopIds(shopIds);
        if (!shopResponse.isSuccess()) {
            throw new LuckException(shopResponse.getMsg());
        }
        List<ShopDetailVO> shopDetailList = shopResponse.getData();
        Map<Long, String> shopMap = shopDetailList.stream().collect(Collectors.toMap(ShopDetailVO::getShopId, ShopDetailVO::getShopName));
        for (SpuVO spuVO : spuList) {
            if (!shopMap.containsKey(spuVO.getShopId())) {
                continue;
            }
            spuVO.setShopName(shopMap.get(spuVO.getShopId()));
        }
        return spuList;
    }

    @Override
    public void verifySpuData() {
        Date currentTime = new Date();
        // 获取数据库商品更新的数量
        ProductSearchDTO productSearchDTO = new ProductSearchDTO();
        //Long spuNum = spuMapper.getNotDeleteSpuNum(currentTime);
        Long spuNum = spuMapper.getAllSpuNum(currentTime);
        productSearchDTO.setPageSize(1);
        productSearchDTO.setPageNum(1);
        // 需要获取被删除的商品，否则数量不对
        productSearchDTO.setGetDelete(1);
        // 数量相同，不需要更新
        if (verifySpuNum(currentTime, productSearchDTO, spuNum)) {
            return;
        }
        PageDTO pageDTO = new PageDTO();
        pageDTO.setPageSize(Constant.MAX_PAGE_SIZE);
        pageDTO.setPageNum(1);
        List<Long> updateList = new ArrayList<>();
        ProductSearchDTO simpleDTO = new ProductSearchDTO();
        while (spuNum > 0) {
            // 每十次循环判断下，数据库与es中的商品数量是否一致了, 一致则不需要再更新
            boolean notUpdate = pageDTO.getPageNum() % 10 == 0 && verifySpuNum(currentTime, productSearchDTO, null) && CollUtil.isEmpty(updateList);
            if (notUpdate) {
                return;
            }
            //PageVO<Spu> page = PageUtil.doPage(pageDTO, () -> spuMapper.listNotDeleteSpu(currentTime));
            PageVO<Spu> page = PageUtil.doPage(pageDTO, () -> spuMapper.listAllSpu(currentTime));
            if (CollUtil.isEmpty(page.getList())) {
                break;
            }
            List<Long> spuIds = new ArrayList<>();
            for (Spu spu : page.getList()) {
                spuIds.add(spu.getSpuId());
            }
            simpleDTO.setSpuIds(spuIds);
            // 需要获取被删除的商品，否则数量不对
            simpleDTO.setGetDelete(1);
            ServerResponseEntity<List<SpuSearchVO>> spuResponseEntity = searchSpuFeignClient.simpleList(simpleDTO);
            if (spuResponseEntity.isFail()) {
                throw new LuckException(spuResponseEntity.getMsg());
            }
            Map<Long, Date> spuMap = spuResponseEntity.getData().stream().collect(Collectors.toMap(SpuSearchVO::getSpuId, SpuSearchVO::getUpdateTime));
            for (Spu spu : page.getList()) {
                boolean isSame = spuMap.containsKey(spu.getSpuId()) && DateUtil.isSameTime(spu.getUpdateTime(), spuMap.get(spu.getSpuId()));
                if (isSame) {
                    continue;
                }
                updateList.add(spu.getSpuId());
            }
            if (updateList.size() > Constant.MAX_DATA_HANDLE_NUM) {
                spuMapper.updateSpuUpdateTime(updateList, null, null, null);
                updateList.clear();
            }
            spuNum = spuNum - Constant.MAX_PAGE_SIZE;
            pageDTO.setPageNum(pageDTO.getPageNum() + 1);
        }
        if (CollUtil.isNotEmpty(updateList)) {
            spuMapper.updateSpuUpdateTime(updateList, null, null, null);
        }
    }

    @Override
    public SpuAppVO prodInfo(Long spuId) {
        SpuServiceImpl spuService = (SpuServiceImpl) AopContext.currentProxy();
        // 商品信息
        SpuVO spu = spuService.getBySpuId(spuId);
        // 如果商品未上架，直接返回
        if (!Objects.equals(spu.getStatus(), StatusEnum.ENABLE.value())) {
            this.updateSpuUpdateTime(Collections.singletonList(spuId), null, null, null);
            throw new LuckException("商品已下架");
        }
        ProductLangUtil.spu(spu);
        ProductLangUtil.spuDetail(spu);
        // 检验店铺信息
        this.checkShopStatusIsOpen(spu.getShopId());
        // 判断同城配送情况
        this.checkSameCity(spu);
        SpuAppVO spuAppVO = mapperFacade.map(spu, SpuAppVO.class);
        spuAppVO.setSpuName(spu.getName());

        // 插入商品销量和评论数量
        this.loadSpuSale(spuId, spuService, spu, spuAppVO);

        // 商品sku
        List<SkuVO> skuList = skuService.listSkuWithAttrBySpuId(spu.getSpuId());

        // 代销商品且是供应商发货，更改商品运费模板、商品sku信息替换为供应商商品sku信息
        if (Objects.nonNull(spu.getSupplierSpuType()) && Objects.equals(spu.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
            this.handleSupplierDelivery(spuService, spu, spuAppVO, skuList);
        }

        // 启用的sku，app查询到的商品是启用sku的商品
        skuList = skuList.stream().filter(skuVO -> Objects.equals(skuVO.getStatus(), StatusEnum.ENABLE.value())).collect(Collectors.toList());
        // 获取商品sku的国际化信息
        ProductLangUtil.skuList(skuList);

        // 拼接sku属性
        List<SkuAppVO> skuAppList = new ArrayList<>();
        for (SkuVO sku : skuList) {
            SkuAppVO skuAppVO = mapperFacade.map(sku, SkuAppVO.class);
            skuAppVO.setProperties(skuService.spliceProperties(sku.getSpuSkuAttrValues()));
            skuAppList.add(skuAppVO);
        }

        spuAppVO.setSkus(skuAppList);
        return spuAppVO;
    }

    private void handleSupplierDelivery(SpuServiceImpl spuService, SpuVO spu, SpuAppVO spuAppVO, List<SkuVO> skuList) {
        // 获取供应商商品spu
        SpuVO spupplierSpu = spuService.getBySpuId(spuAppVO.getSupplierSpuId());
        spuAppVO.setDeliveryTemplateId(spupplierSpu.getDeliveryTemplateId());
        //获取供应商品sku
        List<SkuVO> supplierSkuList = skuService.listSkuWithAttrBySpuId(spu.getSupplierSpuId());
        Map<Long, SkuVO> skuMap = supplierSkuList.stream().collect(Collectors.toMap(SkuVO::getSkuId, s -> s));
        Iterator<SkuVO> iterator = skuList.iterator();
        while (iterator.hasNext()) {
            SkuVO skuVO = iterator.next();
            SkuVO supplierSkuVO = skuMap.get(skuVO.getSupplierSkuId());
            // 判断是否需要删除
            boolean isDelete = Objects.isNull(supplierSkuVO) ||
                    Objects.equals(supplierSkuVO.getStatus(), null) ||
                    Objects.equals(supplierSkuVO.getStatus(), 0) ||
                    Objects.equals(supplierSkuVO.getStatus(), -1);
            //供应商商品信息
            if (isDelete) {
                iterator.remove();
                continue;
            }
            skuVO.setWeight(supplierSkuVO.getWeight());
            skuVO.setVolume(supplierSkuVO.getVolume());
            skuVO.setSupplyPriceFee(supplierSkuVO.getPriceFee());
            skuVO.setSupplierSkuCode(supplierSkuVO.getPartyCode());
            skuVO.setSupplierSkuStatus(supplierSkuVO.getStatus());
            if (supplierSkuVO.getStatus() >= 0) {
                skuVO.setIsSell(supplierSkuVO.getStatus());
            }
        }
    }

    /**
     * 插入商品销量和评论数量
     *
     * @param spuId
     * @return
     */
    private void loadSpuSale(Long spuId, SpuServiceImpl spuService, SpuVO spu, SpuAppVO spuAppVO) {
        SpuExtension spuExtension = spuService.getSpuExtension(spuId);
//            spuExtension.setSaleNum(commissionSpuExtension.getSaleNum());
//        }else {
//            spuExtension = spuService.getSpuExtension(spuId);
//        }
        spuAppVO.setTotalStock(spuExtension.getStock());
        spuAppVO.setSaleNum(spuExtension.getSaleNum() + spuExtension.getWaterSoldNum());
        spuAppVO.setCommentNum(spuExtension.getCommentNum());
    }

    @Override
    public void offlineSpuByShopIds(Integer type, List<Long> shopIds) {
        if (CollUtil.isEmpty(shopIds)) {
            return;
        }
        List<Long> spuIds = spuMapper.listSpuIdByShopIdsAndStatus(SysTypeEnum.MULTISHOP.value(), shopIds, StatusEnum.ENABLE.value(), null);
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        // 删除商品分组信息
        this.handleStatusChange(spuIds);
        if (3 == type) {
            logger.info("通过店铺ids下架店铺商品");
            spuOfflineService.offlineSpuStatusAndActivity(3, spuIds, null, null, null, shopIds);
        } else {
            logger.info("通过商品id修改商品类型");
            spuOfflineService.offlineSpuStatusAndActivity(type, spuIds, null, null, null, null);
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SPU_KEY, key = "#spuId")
    public void toTopBySpuId(Long spuId) {
        spuMapper.toTopBySpuId(spuId);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SPU_KEY, key = "#spuId")
    public void removeSpuCacheBySpuId(Long spuId) {

    }

    @Override
    public List<Long> listSpuIdsByShopIds(List<Long> shopIds) {
        if (CollUtil.isEmpty(shopIds)) {
            return new ArrayList<>();
        }
        return spuMapper.getSpuIdsByShopIds(shopIds);
    }

    @Override
    public void removeBrandOfSpu(Long brandId) {
        spuMapper.removeBrandOfSpu(brandId);
    }

    @Override
    public ServerResponseEntity<Void> checkSpuStatus(List<Long> spuIds) {
        List<SpuVO> spuList = spuMapper.listSpuStatusByIds(spuIds);
        spuList.forEach(spuVO -> {
            if (!Objects.equals(spuVO.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException(ResponseEnum.SPU_STATUS_ERROR, spuVO.getSpuId());
            }
        });
        return ServerResponseEntity.success();
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void batchOffile(OfflineHandleEventDTO offlineHandleEventDto) {
        List<SpuVO> spuList = spuMapper.listSpuStatusByIds(offlineHandleEventDto.getHandleIds());
        ProductLangUtil.spuList(spuList);
        if (CollUtil.isEmpty(spuList)) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }
        List<OfflineHandleEventDTO> offlineHandleEventList = new ArrayList<>();
        List<Long> spuIds = new ArrayList<>();
        List<String> spuNames = new ArrayList<>();
        for (SpuVO spuVO : spuList) {
            //如果是供应商品 给代销商品增加供应商品变更值
            if (Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value())) {
                List<Long> spuIdList = spuMapper.getSupIdListBySupplierId(spuVO.getSpuId());
                if (CollUtil.isNotEmpty(spuIdList)) {
                    spuMapper.batchChangeSynUpdate(spuIdList, IsSynUpdate.NO_CHANGE.value());
                }
            }
            if (!Objects.equals(spuVO.getStatus(), SpuStatus.OFF_SHELF.value()) && !Objects.equals(spuVO.getStatus(), SpuStatus.PUT_SHELF.value())) {
                spuNames.add(spuVO.getName());
                continue;
            }
            OfflineHandleEventDTO offlineHandleEvent = new OfflineHandleEventDTO();
            //设置sysType
            if (Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.NO.value()) || Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.CONSIGNMENT.value())) {
                offlineHandleEvent.setSysType(SysTypeEnum.MULTISHOP.value());
            }
            if (Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value())) {
                offlineHandleEvent.setSysType(SysTypeEnum.SUPPLIER.value());
            }
            offlineHandleEvent.setHandleId(spuVO.getSpuId());
            offlineHandleEvent.setHandleType(OfflineHandleEventType.PROD.getValue());
            offlineHandleEvent.setOfflineReason(offlineHandleEventDto.getOfflineReason());
            spuIds.add(spuVO.getSpuId());
            offlineHandleEventList.add(offlineHandleEvent);
        }
        if (CollUtil.isEmpty(offlineHandleEventList)) {
            throw new LuckException("您选择的商品数据已发生改变，请刷新后重试");
        }

        // 批量新增下线事件记录
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.batchSave(offlineHandleEventList);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        // 批量更新活动状态为下线状态
        batchChangeSpuStatus(spuIds, StatusEnum.OFFLINE.value());
        //批量发送商品下架消息给商家或供应商：商品xxx已被平台或供应商下架，点击去查看
        List<Long> supplierIds = spuList.stream().filter(s -> Objects.equals(s.getSupplierSpuType(), SupplierSpuType.YES.value())).map(SpuVO::getSupplierId).collect(Collectors.toList());
        ServerResponseEntity<List<SupplierApiDetailVO>> supplierResp = supplierDetailFeignClient.listSupplierDetailBySupplierIds(supplierIds);
        Map<Long, String> supplierNameMap = supplierResp.getData().stream().collect(Collectors.toMap(SupplierApiDetailVO::getSupplierId, SupplierApiDetailVO::getSupplierName));

        List<SendNotifyBO> notifyList = new ArrayList<>();
        for (SpuVO spuVO : spuList) {
            SendNotifyBO sendNotifyBO = new SendNotifyBO();
            if (Objects.nonNull(spuVO.getSupplierSpuType()) && Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value())) {
                sendNotifyBO.setShopId(null);
                sendNotifyBO.setSupplierId(spuVO.getSupplierId());
            } else {
                sendNotifyBO.setShopId(spuVO.getShopId());
                sendNotifyBO.setSupplierId(null);
            }
            sendNotifyBO.setSendType(Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value()) ? SendTypeEnum.PRODUCT_OFFLINE_TO_SUPPLIER.getValue() : SendTypeEnum.PRODUCT_OFFLINE.getValue());
            sendNotifyBO.setSpuId(spuVO.getSpuId());
            sendNotifyBO.setSpuName(spuVO.getName());
            sendNotifyBO.setSupplierName(Objects.equals(spuVO.getSupplierSpuType(), SupplierSpuType.YES.value()) ? supplierNameMap.get(spuVO.getSupplierId()) : null);
            notifyList.add(sendNotifyBO);
        }


        SendStatus sendStockStatus = sendProductNotifyToShopTemplate.syncSend(RocketMqConstant.SEND_PRODUCT_NOTIFY_TO_SHOP_TOPIC, new GenericMessage<>(notifyList)).getSendStatus();
        if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    public List<SpuSimpleBO> listSimple(SpuSimpleBO spuSimpleBO) {
        return spuMapper.listSimple(spuSimpleBO);
    }

    @Override
    public List<SpuSimpleBO> listSimples(SpuSimpleBO spuSimpleBO) {
        return spuMapper.listSimples(spuSimpleBO);
    }

    private Boolean verifySpuNum(Date currentTime, ProductSearchDTO productSearchDTO, Long spuNum) {
        if (Objects.isNull(spuNum)) {
            //spuNum = spuMapper.getNotDeleteSpuNum(currentTime);
            spuNum = spuMapper.getAllSpuNum(currentTime);
        }
        ServerResponseEntity<EsPageVO<SpuAdminVO>> responseEntity = searchSpuFeignClient.adminPage(productSearchDTO);
        if (responseEntity.isFail()) {
            throw new LuckException(responseEntity.getMsg());
        }
        Long total = responseEntity.getData().getTotal();
        // 数量相同，不需要更新
        return Objects.equals(spuNum, total);
    }


    private void checkShopStatusIsOpen(Long shopId) {
        Date now = new Date();
        ServerResponseEntity<EsShopDetailBO> shopDetailRes = shopDetailFeignClient.getShopByShopId(shopId);
        if (shopDetailRes.isFail()) {
            throw new LuckException(shopDetailRes.getMsg());
        }
        EsShopDetailBO esShopDetailBO = shopDetailRes.getData();
        if (Objects.equals(esShopDetailBO.getShopStatus(), ShopStatus.OPEN.value())) {
            return;
        }
        if (Objects.equals(esShopDetailBO.getShopStatus(), ShopStatus.OFFLINE.value()) || Objects.equals(esShopDetailBO.getShopStatus(), ShopStatus.OFFLINE_AWAIT_AUDIT.value())) {
            throw new LuckException("店铺已下线");
        }
        if (Objects.equals(esShopDetailBO.getShopStatus(), ShopStatus.STOP.value())) {
            if (now.compareTo(esShopDetailBO.getContractStartTime()) < 0) {
                throw new LuckException("店铺未开始营业");
            } else {
                throw new LuckException("店铺已停止营业");
            }
        }
    }

    private void checkSameCity(SpuVO spuVO) {
        SpuVO.DeliveryModeVO deliveryModeVO = Json.parseObject(spuVO.getDeliveryMode(), SpuVO.DeliveryModeVO.class);
        // 商品不支持同城配送
        if (!deliveryModeVO.getHasCityDelivery()) {
            spuVO.setCityDelivery(false);
            return;
        }
        ServerResponseEntity<SameCityVO> responseEntity = sameCityFeignClient.getSameCityByShopId(spuVO.getShopId());
        if (responseEntity.isFail()) {
            spuVO.setCityDelivery(false);
        }
        SameCityVO sameCityVO = responseEntity.getData();
        if (Objects.isNull(sameCityVO) || sameCityVO.getStatus() == 0) {
            spuVO.setCityDelivery(false);
        } else {
            spuVO.setCityDelivery(true);
        }
    }

    /**
     * 校验spu新增或更新信息
     *
     * @param spuDTO
     * @param saveProd true: 保存，false: 更新
     */
    private void checkSaveOrUpdateInfo(SpuDTO spuDTO, boolean saveProd) {
        Long tenantId = AuthUserContext.get().getTenantId();
        Integer sysType = AuthUserContext.get().getSysType();
        if (!Objects.equals(Constant.PLATFORM_SHOP_ID, tenantId) && Objects.isNull(spuDTO.getShopCategoryId()) && Objects.equals(sysType, SysTypeEnum.MULTISHOP.value())) {
            throw new LuckException("店铺分类不能为空");
        }
        if (Objects.isNull(spuDTO.getCategoryId()) && !Objects.equals(spuDTO.getSpuType(), SpuType.SCORE.value())) {
            throw new LuckException("平台分类不能为空");
        }
        if (saveProd) {
            if (Objects.equals(sysType, SysTypeEnum.MULTISHOP.value())) {
                // 发布商品时，需要根据店铺或供应商状态判断是否可以发布商品
                ServerResponseEntity<EsShopDetailBO> shopRequest = shopDetailFeignClient.getShopByShopId(tenantId);
                EsShopDetailBO shopDetail = shopRequest.getData();
                if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
                    throw new LuckException("店铺处于违规下线状态，不能发布新商品");
                }
                if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AWAIT_AUDIT.value())) {
                    throw new LuckException("店铺上线申请待审核中，不能发布新商品");
                }
            } else if (Objects.equals(sysType, SysTypeEnum.SUPPLIER.value())) {
                ServerResponseEntity<SupplierDetailBO> supplierRequest = supplierDetailFeignClient.getSupplierBySupplierId(tenantId);
                SupplierDetailBO supplierDetail = supplierRequest.getData();
                if (Objects.equals(supplierDetail.getSupplierStatus(), SupplierStatus.OFFLINE.value())) {
                    throw new LuckException("供应商处于违规下线状态，不能发布新商品");
                }
                if (Objects.equals(supplierDetail.getSupplierStatus(), SupplierStatus.OFFLINE_AWAIT_AUDIT.value())) {
                    throw new LuckException("供应商上线申请待审核中，不能发布新商品");
                }
            }
            // 校验平台分类是否处于上架状态
            CategoryVO platformCategory = categoryMapper.getById(spuDTO.getCategoryId());
            // 积分商品不需要分类
            if (!Objects.equals(spuDTO.getSpuType(), SpuType.SCORE.value())) {
                //如果是下架了分类，就提示 该平台分类已被下线，无法上架该商品
                //如果是签约丢了，就提示 您已取消与该商品类型的签约，请重新签约该商品类型方可上架
                if (Objects.isNull(platformCategory) || !Objects.equals(platformCategory.getStatus(), StatusEnum.ENABLE.value())) {
                    throw new LuckException("该平台分类已被下线，无法上架该商品");
                }
                if (!Objects.equals(tenantId, Constant.PLATFORM_SHOP_ID)) {
                    // 判断当前店铺是否可用使用该平台分类
                    int signingCount = categoryShopMapper.countByShopIdAndCategoryId(tenantId, spuDTO.getCategoryId(), sysType);
                    if (signingCount == 0) {
                        throw new LuckException("您已取消与该商品类型的签约，请重新签约该商品类型方可上架");
                    }
                }
            } else {
                spuDTO.setCategoryId(0L);
            }
        }
        //spu编码不能重复
        if (Objects.nonNull(spuDTO.getSpuCode()) && !Objects.equals(spuDTO.getSpuCode(), "")) {
            int count = spuMapper.getCountBySpuCode(spuDTO.getSpuCode(), spuDTO.getSpuId(), spuDTO.getSupplierSpuId());
            if (count > 0) {
                //存在生成新的
                String spuCode = StringUtils.join("P", segmentFeignClient.getSegmentId(DistributedIdKey.MALL4CLOUD_PRODUCT_SKU_CODE).getData());
                spuDTO.setSpuCode(spuCode);
//                throw new LuckException("spu编码不能重复");
            }
        }
        // 校验店铺分类是否可用
        if (!Objects.equals(Constant.PLATFORM_SHOP_ID, tenantId) && Objects.equals(sysType, SysTypeEnum.MULTISHOP.value()) && Objects.nonNull(spuDTO.getShopCategoryId())) {
            CategoryVO shopCategory = categoryMapper.getById(spuDTO.getShopCategoryId());
            if (Objects.isNull(shopCategory) || !Objects.equals(shopCategory.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException("当前选择的店铺分类已下架或已删除， 请重新选择店铺分类");
            }
        }
        // 校验供应商分类是否可用
        if (!Objects.equals(Constant.PLATFORM_SHOP_ID, tenantId) && Objects.equals(sysType, SysTypeEnum.SUPPLIER.value()) && Objects.nonNull(spuDTO.getSupplierCategoryId())) {
            CategoryVO supplierCategory = categoryMapper.getById(spuDTO.getSupplierCategoryId());
            if (Objects.isNull(supplierCategory) || !Objects.equals(supplierCategory.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException("当前选择的供应商分类已下架或已删除， 请重新选择供应商分类");
            }
        }
        // 校验品牌是否可用
        if (Objects.nonNull(spuDTO.getBrandId()) && !Objects.equals(spuDTO.getBrandId(), 0L)) {
            BrandVO brandVO = brandMapper.getByBrandId(spuDTO.getBrandId());
            if (Objects.isNull(brandVO) || !Objects.equals(brandVO.getStatus(), StatusEnum.ENABLE.value())) {
                throw new LuckException("当前选择的品牌已下架或已删除，请重新选择品牌");
            }
            if (!Objects.equals(tenantId, Constant.PLATFORM_SHOP_ID)) {
                if (!Objects.equals(spuDTO.getSupplierSpuType(), SupplierDeliveryType.SHOP_DELIVERY.value())) {
                    // 判断当前店铺是否可以使用该品牌
                    int categoryBrandCount = categoryBrandService.countByBrandIdAndCategoryId(spuDTO.getBrandId(), spuDTO.getCategoryId());
                    if (categoryBrandCount == 0) {
                        int signingCount = brandShopService.countByShopIdAndBrandId(tenantId, spuDTO.getBrandId(), sysType);
                        if (signingCount == 0) {
                            throw new LuckException("当前选择的品牌签约关系已失效，请重新选择品牌");
                        }
                    }
                }
            }
        }
        //校验运费模板
        if (Objects.nonNull(spuDTO.getDeliveryTemplateId())) {
            //发货方式为仓库发货才校验
            if (Objects.nonNull(spuDTO.getSupplierDeliveryType()) && Objects.equals(spuDTO.getSupplierDeliveryType(), SupplierDeliveryType.SHOP_DELIVERY.value())) {
                ServerResponseEntity<List<ShopTransportVO>> response = deliveryFeignClient.listTransportByShopId(spuDTO.getShopId());
                if (!Objects.equals(response.getCode(), ResponseEnum.OK.value())) {
                    throw new LuckException(response.getMsg());
                }
                Set<Long> transportIds = response.getData().stream().map(ShopTransportVO::getTransportId).collect(Collectors.toSet());
                if (!transportIds.contains(spuDTO.getDeliveryTemplateId())) {
                    throw new LuckException("产品运费模板不存在");
                }
            }
        }
        if (Objects.isNull(spuDTO.getSeq())) {
            spuDTO.setSeq(0);
        }
        if (Objects.isNull(spuDTO.getBrandId())) {
            spuDTO.setBrandId(0L);
        }
        if (Objects.isNull(spuDTO.getVideo())) {
            spuDTO.setVideo("");
        }
        List<String> partyCodes = skuService.listSkuPartyCodesByShopId(tenantId, sysType, spuDTO.getSpuId());
        for (SkuDTO sku : spuDTO.getSkuList()) {
            // 生成商品编码
            if (StrUtil.isBlank(sku.getPartyCode())) {
                String partyCode = StringUtils.join("P", segmentFeignClient.getSegmentId(DistributedIdKey.MALL4CLOUD_PRODUCT_SKU_CODE).getData());
                sku.setPartyCode(partyCode);
            }
            if (CollectionUtils.isNotEmpty(partyCodes) && partyCodes.contains(sku.getPartyCode())) {
                // 商品编码已存在,生成新的
                String partyCode = StringUtils.join("P", segmentFeignClient.getSegmentId(DistributedIdKey.MALL4CLOUD_PRODUCT_SKU_CODE).getData());
                sku.setPartyCode(partyCode);
//                throw new LuckException("商品编码已存在");
            }
        }
        List<GiveawaySpuVO> giveawaySpuList = giveawaySpuMapper.getBySpuId(spuDTO.getSpuId());
        if (CollectionUtils.isNotEmpty(giveawaySpuList) && !Objects.equals(spuDTO.getPreSaleType(), PreSaleType.DISABLE.value())) {
            // 参与赠品活动的商品不能添加为定金预售商品
            throw new LuckException("参与赠品活动的赠品不能添加为预售商品");
        }
    }

    @Override
    public Integer isCommissionByShopIdAndSpuId(Long shopId, Long supplierSpuId) {
        return spuMapper.isCommissionByShopIdAndSpuId(shopId, supplierSpuId);
    }

    @Override
    public SupplierSpuVo getSupplierInfoBySpuId(Long spuId, Long shopId) {
        SupplierSpuVo supplierSpuVo = new SupplierSpuVo();
        SpuVO spu = spuMapper.getBySpuId(spuId);
        //编辑返回数据
        supplierSpuVo.setSupplierSpuId(spu.getSpuId());
        supplierSpuVo.setMainImgUrl(spu.getMainImgUrl());
        supplierSpuVo.setImgUrls(spu.getImgUrls());
        supplierSpuVo.setSellingPoint(spu.getSellingPoint());
        supplierSpuVo.setVideo(spu.getVideo());
        supplierSpuVo.setMeasureUnit(spu.getMeasureUnit());
        supplierSpuVo.setSpuCode(spu.getSpuCode());
        supplierSpuVo.setCategoryId(spu.getCategoryId());
        supplierSpuVo.setShopCategoryId(spu.getShopCategoryId());
        supplierSpuVo.setSupplierId(spu.getSupplierId());
        supplierSpuVo.setSpuLangList(spu.getSpuLangList());
        supplierSpuVo.setDetail(spu.getDetail());
        supplierSpuVo.setDetailList(spu.getDetailList());
        supplierSpuVo.setBrandId(spu.getBrandId());
        supplierSpuVo.setHasSkuImg(spu.getHasSkuImg());
        //返回数据时根据智能代销设置销售价
        //获取店铺的代销设置
        ServerResponseEntity<ShopSubstituteSalesVO> sales = shopSubstituteSalesFeignClient.getByShopSubstituteSalesId(shopId);
        ShopSubstituteSalesVO data = sales.getData();
        //sku信息
        List<SkuVO> skuVOS = skuService.listSkuAllInfoBySpuId(spuId, false);
        for (SkuVO skuVO : skuVOS) {
            List<SkuLangVO> skuLang = skuLangService.getBySkuId(skuVO.getSkuId());
            skuVO.setSkuLangList(skuLang);
            //设置供货价
            skuVO.setSupplyPriceFee(skuVO.getPriceFee());
            if (!Objects.isNull(data)) {
                //代销设置为智能设价时,计算代销商品售价
                if (data.getSalesType() != 1) {
                    Long price = 0L;
                    if (data.getSalesPriceType() == 0) {
                        //按比例加价
                        price = PriceUtil.divideByBankerRounding(spu.getPriceFee() * data.getSalesPrice(), 100) + spu.getPriceFee();
                    }
                    if (data.getSalesPriceType() == 1) {
                        //按固定数值加价
                        price = skuVO.getPriceFee() + data.getSalesPrice();
                    }
                    skuVO.setPriceFee(price);
                }
            }
            //判断sku状态是否可售
            skuVO.setIsSell(SkuIsSell.NO_SELL.value());
            if (skuVO.getStatus() == 1) {
                skuVO.setIsSell(SkuIsSell.CAN_SELL.value());
            }
            if (skuVO.getStatus() == 0) {
                skuVO.setIsSell(SkuIsSell.NO_SELL.value());
            }
            skuVO.setStockWarning(0L);
        }
        supplierSpuVo.setSkus(skuVOS);
        return supplierSpuVo;
    }

    @Override
    public List<Long> getSupplierSupIdBySkuId(Long skuId) {
        return null;
    }

//    @Override
//    public List<Long> getSupplierSupIdBySkuId(Long skuId) {
//        return spuMapper.getSupplierSupIdBySkuId(skuId);
//    }

    @Override
    public void soldOutSpu(Long skuId, Long supplierPrice) {
        SkuVO skuBySkuId = skuMapper.getSkuBySkuId(skuId);
        SpuVO bySpuId = spuMapper.getBySpuId(skuBySkuId.getSpuId());
        if (Objects.equals(bySpuId.getSupplierSpuType(), SupplierSpuType.YES.value())) {
            //查询代销商品
            List<Spu> supplierSup = spuMapper.getSupplierSupIdBySkuId(skuId);
            for (int i = 0; i < supplierSup.size(); i++) {
                Long shopId = supplierSup.get(i).getShopId();
                //获取代销商品sku信息
                Long spuSkuId = skuMapper.getSkuIdBySpuIdAndSupplierSkuId(supplierSup.get(i).getSpuId(), skuId);
                //过滤掉没有设置手动设价的店铺
                ServerResponseEntity<ShopSubstituteSalesVO> salesType = shopSubstituteSalesFeignClient.getByShopSubstituteSalesId(shopId);
                if (!Objects.isNull(salesType.getData())) {
                    //智能设价 商家发货的代销商品不需要修改价格
                    if (Objects.equals(salesType.getData().getSalesType(), 0) && Objects.equals(supplierSup.get(i).getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                        //重新计算售价
                        //智能设价计算售价
                        Long priceFee = 0L;
                        if (salesType.getData().getSalesPriceType() == 0) {
                            //按比例加价
                            priceFee = PriceUtil.divideByBankerRounding(supplierPrice * salesType.getData().getSalesPrice(), 10000) + supplierPrice;
                        }
                        if (salesType.getData().getSalesPriceType() == 1) {
                            //按固定数值加价
                            priceFee = supplierPrice + salesType.getData().getSalesPrice();
                        }
                        //更新sku
                        Sku sku = new Sku();
                        sku.setSkuId(spuSkuId);
                        sku.setPriceFee(priceFee);
                        sku.setMarketPriceFee(priceFee);
                        skuMapper.update(sku);
                        break;
                    }
                    //没有设置供货价高于代销价时自动下架的移除
                    if (Objects.equals(salesType.getData().getAutomaticOff(), 0)) {
                        supplierSup.remove(i);
                        break;
                    }
                    //获取代销商品sku代销价
                    Long spuId = supplierSup.get(i).getSpuId();
                    Long priceFee = skuMapper.getPriceFeeBySpuIdAndSupplierSkuId(spuId, skuId);
                    //下架商品
                    Spu spu = new Spu();
                    spu.setSpuId(spuId);
                    spu.setStatus(SpuStatus.OFF_SHELF.value());
                    spuMapper.update(spu);
//                }
                }
            }
        }
    }

    @Override
    public void importSupplierSpu(List<Long> supplierSpuId) {
        for (int i = 0; i < supplierSpuId.size(); i++) {
            importSupplierSpuService.importSpu(supplierSpuId.get(i), AuthUserContext.get().getTenantId(), AuthUserContext.get().getSysType(),
                    AuthUserContext.get().getUserId(), false);
        }
    }


    @Override
    public Long setPriceFee(SkuVO skuVO) {
        Long shopId = AuthUserContext.get().getTenantId();
        //获取商家代销设置
        ServerResponseEntity<ShopSubstituteSalesVO> salesType = shopSubstituteSalesFeignClient.getByShopSubstituteSalesId(shopId);
        ShopSubstituteSalesVO shopSubstituteSalesVO = salesType.getData();
        if (!Objects.isNull(shopSubstituteSalesVO)) {
            if (shopSubstituteSalesVO.getSalesType() == 0) {
                //智能设价计算售价
                Long price = 0L;
                if (shopSubstituteSalesVO.getSalesPriceType() == 0) {
                    //按比例加价
                    price = PriceUtil.divideByBankerRounding(skuVO.getPriceFee() * shopSubstituteSalesVO.getSalesPrice(), 10000) + skuVO.getPriceFee();
                }
                if (shopSubstituteSalesVO.getSalesPriceType() == 1) {
                    //按固定数值加价
                    price = skuVO.getPriceFee() + shopSubstituteSalesVO.getSalesPrice();
                }
                return price;
            }
        }
        return 0L;
    }


    @Override
    public SpuVO getSpuByShopIdAndSupplierSpuId(Long shopId, Long supplierSpuId) {
        return spuMapper.getSpuByShopIdAndSupplierSpuId(shopId, supplierSpuId);
    }

    @Override
    public List<SpuVO> supplierSpuList(SpuPageSearchDTO spu) {
        return spuMapper.supplierSpuList(spu);
    }

    @Override
    public List<SpuVO> getSpuIdsBySupplierIdAndSupplierSpuType(Long supplierId, Date createTime, Integer supplierSpuType) {
        return spuMapper.getSpuIdsBySupplierIdAndSupplierSpuType(supplierId, createTime, supplierSpuType);
    }

    @Override
    public List<SpuVO> listMerchantSpuIdsBySupplierId(Long supplierId) {
        return spuMapper.listMerchantSpuIdsBySupplierId(supplierId);
    }

    @Override
    public List<SpuVO> listSpuByShopIdAndSupplierSpuId(Long shopId, List<Long> supplierSpuIds) {
        return spuMapper.listSpuByShopIdAndSupplierSpuId(shopId, supplierSpuIds);
    }

    @Override
    public void soldOutSpuBySpu(Long spuId, Long price, Long marketPriceFee) {
        List<SpuVO> spuVos = spuMapper.listSpuBySupplierSpuId(spuId);
        if (spuVos.size() == 0) {
            return;
        }
        // 获取商家代销设置
        List<Long> shopIds = spuVos.stream().map(SpuVO::getShopId).collect(Collectors.toList());
        ServerResponseEntity<List<ShopSubstituteSalesVO>> listServerResponseEntity = shopSubstituteSalesFeignClient.shopSubstituteSalesList(shopIds);
        if (listServerResponseEntity.isFail()) {
            throw new LuckException(listServerResponseEntity.getMsg());
        }
        Map<Long, ShopSubstituteSalesVO> salesVOMap = listServerResponseEntity.getData().stream().collect(Collectors.toMap(ShopSubstituteSalesVO::getShopId, s -> s));
        for (SpuVO spuVo : spuVos) {
            ShopSubstituteSalesVO shopSubstituteSalesVO = salesVOMap.get(spuVo.getShopId());
            if (Objects.isNull(shopSubstituteSalesVO)) {
                continue;
            }
            // 手动设价不执行
            if (Objects.equals(shopSubstituteSalesVO.getSalesType(), SalesType.MANUAL_OPERATION_PRICE.value())) {
                continue;
            }
            Long priceFee = 0L;
            if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.PROPORTION_PRICE.value())) {
                // 按比例加价
                priceFee = PriceUtil.divideByBankerRounding(price * shopSubstituteSalesVO.getSalesPrice(), 10000) + price;
            }
            if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.FIXED_NUMBER_PRICE.value())) {
                // 按固定数值加价
                priceFee = price + shopSubstituteSalesVO.getSalesPrice();
            }
            Spu spu = new Spu();
            spu.setSpuId(spuVo.getSpuId());
            spu.setPriceFee(priceFee);
            spu.setMarketPriceFee(marketPriceFee);
            spuMapper.update(spu);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offlineSpuBySupplierId(Long supplierId) {
        List<SpuVO> supplierVoList = spuMapper.getSupplierSpuBySupplierId(supplierId, StatusEnum.ENABLE.value());
        if (CollectionUtil.isEmpty(supplierVoList)) {
            return;
        }
        spuMapper.offlineSpuBySupplierId(supplierId);
        List<Long> supplierSpuIdList = supplierVoList.stream().map(e -> e.getSpuId()).collect(Collectors.toList());
        List<Long> spuIdList = spuMapper.batchSupIdListBySupplierId(supplierSpuIdList);
        if (CollectionUtil.isNotEmpty(spuIdList)) {
            spuMapper.batchChangeSynUpdate(spuIdList, IsSynUpdate.NO_CHANGE.value());
        }
        // 查询出秒杀or团购的商品进行下线
        // 下线掉关联商品的活动
        // 下面这个方法查不到正常状态的商品了，所以需要把修改后的商品状态传过去
//        spuOfflineService.offlineSpuStatusAndActivity(3, null, shopId, null, StatusEnum.DISABLE.value());
    }

    @Override
    public List<SpuVO> listSpuBySupplierSpuId(Long supplierSpuId) {
        return spuMapper.listSpuBySupplierSpuId(supplierSpuId);
    }

    @Override
    public List<SpuVO> getSpuIsSynUpdate(List<Long> spuIds) {
        List<SpuVO> spuIsSynUpdate = spuMapper.getSpuIsSynUpdate(spuIds);
        for (SpuVO spuVO : spuIsSynUpdate) {
            // 库存
            Integer totalStock = skuStockService.getTotalBySpuId(Objects.isNull(spuVO.getSupplierSpuId()) ? spuVO.getSpuId() : spuVO.getSupplierSpuId());
            if (Objects.isNull(totalStock)) {
                totalStock = spuVO.getTotalStock();
            }
            spuVO.setTotalStock(totalStock);
        }
        return spuIsSynUpdate;
    }

    @Override
    public List<Long> getSupIdListBySupplierId(Long supplierId) {
        return spuMapper.getSupIdListBySupplierId(supplierId);
    }

    @Override
    public void batchChangeSynUpdate(List<Long> spuIds, Integer isSynUpdate) {
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        spuMapper.batchChangeSynUpdate(spuIds, isSynUpdate);
    }

    @Override
    public void batchUpdateCommissionSpuDeliverType(List<Long> spuIds, Integer deliverType) {
        if (CollUtil.isEmpty(spuIds)) {
            return;
        }
        spuMapper.batchUpdateCommissionSpuDeliverType(spuIds, deliverType);
    }

    private void offSupplierSendCommissionSpu(SpuDTO spuDTO) {
        //下架商家供应商发货的代销商品
        List<Long> commissionSpuId = spuMapper.getCommissionSpuIdList(spuDTO.getSpuId(), SupplierDeliveryType.SUPPLIER_DELIVERY.value());
        if (CollectionUtil.isNotEmpty(commissionSpuId)) {
            spuMapper.batchChangeSpuStatus(commissionSpuId, SpuStatus.OFF_SHELF.value());
        }
    }

    @Override
    public void supplierSpuUpdateLaterOffSpu(Long supplierSpuId, Integer commissionSpuOffType) {
        if (Objects.equals(commissionSpuOffType, CommissionSpuOffType.ALL.value())) {
            List<Long> commissionSpuIds = spuMapper.getSupIdListBySupplierId(supplierSpuId);
            //下架
            supplierSpuUpdateLaterOperateService.batchChangeSpuStatus(commissionSpuIds, SpuStatus.OFF_SHELF.value(), SysTypeEnum.MULTISHOP.value());
        }

        if (Objects.equals(commissionSpuOffType, CommissionSpuOffType.SUPPLIER_DELIVERY_SPU.value())) {
            List<Long> commissionSpuIds = spuMapper.getCommissionSpuIdList(supplierSpuId, SupplierDeliveryType.SUPPLIER_DELIVERY.value());
            //下架
            batchChangeSpuStatus(commissionSpuIds, SpuStatus.OFF_SHELF.value());
        }

        if (Objects.equals(commissionSpuOffType, CommissionSpuOffType.SHOP_DELIVERY.value())) {
            List<Long> commissionSpuIds = spuMapper.getCommissionSpuIdList(supplierSpuId, SupplierDeliveryType.SHOP_DELIVERY.value());
            //下架
            batchChangeSpuStatus(commissionSpuIds, SpuStatus.OFF_SHELF.value());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateManualPriceCommissionSpuPrice(Long shopId) {
        List<Long> spuIds = spuMapper.getCommissionSpuListByShopId(shopId);
        List<Long> supplierSpuId = spuMapper.getSupplierSpuId(shopId);
        if (CollUtil.isNotEmpty(spuIds)) {
            List<SpuVO> spuVOS = spuMapper.listSpuBySpuIds(spuIds);
            List<SpuVO> supplierSpuVOs = spuMapper.listSpuBySpuIds(supplierSpuId);
            //获取商家代销设置
            ServerResponseEntity<ShopSubstituteSalesVO> salesType = shopSubstituteSalesFeignClient.getByShopSubstituteSalesId(shopId);
            ShopSubstituteSalesVO shopSubstituteSalesVO = salesType.getData();
            if (!Objects.isNull(shopSubstituteSalesVO) && shopSubstituteSalesVO.getSalesType() == 0) {
                for (SpuVO spuVO : spuVOS) {
                    if (Objects.equals(spuVO.getSupplierDeliveryType(), SupplierDeliveryType.SHOP_DELIVERY.value())) {
                        //商家自行发货的不用执行
                        continue;
                    }
                    //供应商商品
                    SpuVO supplierSpuVO = supplierSpuVOs.stream().filter(spuVO1 -> spuVO1.getSpuId().equals(spuVO.getSupplierSpuId())).findFirst().get();
                    //智能设价计算售价
                    Long price = 0L;
                    if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.PROPORTION_PRICE.value())) {
                        //按比例加价
                        price = PriceUtil.divideByBankerRounding(supplierSpuVO.getPriceFee() * shopSubstituteSalesVO.getSalesPrice(), 10000) + supplierSpuVO.getPriceFee();
                    }
                    if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.FIXED_NUMBER_PRICE.value())) {
                        //按固定数值加价
                        price = supplierSpuVO.getPriceFee() + shopSubstituteSalesVO.getSalesPrice();
                    }
                    spuVO.setPriceFee(price);
                    //sku信息
                    List<SkuVO> skuVOS = skuMapper.listSkuWithAttrBySpuId(spuVO.getSpuId());
                    List<SkuVO> supplierSkuVOs = skuMapper.listSkuWithAttrBySpuId(supplierSpuVO.getSpuId());
                    List<Sku> skus = new ArrayList<>();
                    for (SkuVO skuVO : skuVOS) {
                        //供应商sku
                        SkuVO supplierSkuVO = supplierSkuVOs.stream().filter(skuVO1 -> skuVO1.getSkuId().equals(skuVO.getSupplierSkuId())).findFirst().get();
                        //智能设价计算售价
                        Long skuPrice = 0L;
                        if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.PROPORTION_PRICE.value())) {
                            //按比例加价
                            skuPrice = PriceUtil.divideByBankerRounding(supplierSkuVO.getPriceFee() * shopSubstituteSalesVO.getSalesPrice(), 10000) + supplierSkuVO.getPriceFee();
                        }
                        if (Objects.equals(shopSubstituteSalesVO.getSalesPriceType(), SalesPriceType.FIXED_NUMBER_PRICE.value())) {
                            //按固定数值加价
                            skuPrice = supplierSkuVO.getPriceFee() + shopSubstituteSalesVO.getSalesPrice();
                        }
                        skuVO.setPriceFee(skuPrice);
                        Sku sku = mapperFacade.map(skuVO, Sku.class);
                        skus.add(sku);
                    }
                    skuMapper.updateBatch(skus);
                }
                spuMapper.updateBatch(spuVOS);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateSpuAndSkuStock(Long spuId, Long skuId, Integer changeCount) {
        if (skuService.updateSkuStock(skuId, changeCount, spuId) < 1) {
            return false;
        }
        if (spuExtensionService.updateStock(spuId) < 1) {
            return false;
        }
        return true;
    }

    @Override
    public List<SpuVO> getBySpuIds(List<Long> spuIds) {
        List<SpuVO> spuVOS = spuMapper.getBySpuIds(spuIds);
        return spuVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchChangeSpuStatusToDisableBySupplierIds(List<Long> supplierIdsToStop) {
        List<Long> spuIds = spuMapper.listSpuIdByShopIdsAndStatus(SysTypeEnum.SUPPLIER.value(), supplierIdsToStop, StatusEnum.ENABLE.value(), null);
        if (CollectionUtil.isNotEmpty(spuIds)) {
            spuMapper.batchChangeSpuStatus(spuIds, StatusEnum.DISABLE.value());
        }
    }

    @Override
    public List<SpuVO> getCommissionSpuList(Long supplierSpuId) {
        return spuMapper.getCommissionSpuListBySupplierDeliver(supplierSpuId);
    }

    @Override
    public void syncUpdateCommissionSpuBrandOrSeq(Long brandId, Integer seq, Long supplierSpuId) {
        List<SpuVO> commissionSpuList = spuMapper.getCommissionSpuList(supplierSpuId);
        if (commissionSpuList.size() == 0) {
            return;
        }
        List<SpuVO> spuVOList = new ArrayList<>();
        SpuVO spuVO = null;
        for (SpuVO spuVOs : commissionSpuList) {
            spuVO = new SpuVO();
            spuVO.setSpuId(spuVOs.getSpuId());
            if (brandId != -1) {
                spuVO.setBrandId(brandId);
            }
            if (seq != -1) {
                spuVO.setSeq(seq);
            }
            spuVOList.add(spuVO);
        }
        spuMapper.updateBatch(spuVOList);
    }

    @Override
    public PageVO<SpuVO> pageSpuSku(PageDTO pageDTO, SpuDTO spuDTO) {
        PageVO<SpuVO> spuPageVO = new PageVO<>();
        // 全部商品查出，对spu进行分页处理
        List<SpuVO> spuVOList = spuMapper.pageSpuSku(spuDTO, I18nMessage.getLang());
        if (CollectionUtil.isEmpty(spuVOList)) {
            spuPageVO.setList(new ArrayList<>());
            spuPageVO.setTotal(0L);
            spuPageVO.setPages(0);
            return spuPageVO;
        }
        // 对spu进行分组
        Map<Long, List<SpuVO>> spuMap = spuVOList.stream()
                .collect(Collectors.groupingBy(SpuVO::getSpuId, LinkedHashMap::new, Collectors.toList()));
        // stream流分页取数据
        List<SpuVO> data = new ArrayList<>();
        spuMap.entrySet().stream()
                .skip((long) (pageDTO.getPageNum() - 1) * pageDTO.getPageSize())
                .limit(pageDTO.getPageSize())
                .forEach(x -> data.addAll(x.getValue()));
        spuPageVO.setList(data);
        spuPageVO.setTotal(Long.valueOf(String.valueOf(spuMap.keySet().size())));
        spuPageVO.setPages(PageUtil.getPages(spuPageVO.getTotal(), pageDTO.getPageSize()));
        return spuPageVO;
    }

    @Override
    public void voluntarilyImportSupplierSpu(List<SpuVO> spuVOS, Integer sysType, Long userId) {
        for (SpuVO spuVO : spuVOS) {
            SpuVO spu = spuMapper.getSpuByShopIdAndSupplierSpuId(spuVO.getShopId(), spuVO.getSupplierSpuId());
            // 不存在则导入
            if (Objects.isNull(spu)) {
                importSupplierSpuService.importSpu(spuVO.getSupplierSpuId(), spuVO.getShopId(), sysType, userId, true);
            }
        }
    }

    @Override
    public void auditSpu(OfflineHandleEventDTO eventDTO) {
        // 查询商品及其状态
        SpuVO spuVO = spuMapper.getBySpuId(eventDTO.getHandleId());
        if (spuVO == null) {
            throw new LuckException("查找不到该商品信息");
        }
        if (!SpuStatus.PUBLISH_WAIT_AUDIT.value().equals(spuVO.getStatus())) {
            throw new LuckException("商品状态已改变，请刷新页面");
        }
        // 是否审核通过，通过直接修改商品状态；未通过新增一条下线数据，再修改状态
        Spu spu = new Spu();
        spu.setSpuId(eventDTO.getHandleId());
        if (Objects.equals(eventDTO.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            spu.setStatus(SpuStatus.PUT_SHELF.value());
        } else if (Objects.equals(eventDTO.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            eventDTO.setStatus(OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue());
            eventDTO.setHandleType(OfflineHandleEventType.PROD.getValue());
            eventDTO.setSysType(SysTypeEnum.MULTISHOP.value());
            eventDTO.setShopId(spuVO.getShopId());
            eventDTO.setOfflineReason(eventDTO.getRefuseReason());
            offlineHandleEventFeignClient.save(eventDTO);
            spu.setIsTop(0);
            spu.setStatus(SpuStatus.PLATFORM_OFF_SHELF.value());
        }
        spuMapper.update(spu);
    }

    @Override
    public Long stockWarningCount(Long supplierId) {
        return spuMapper.stockWarningCount(supplierId);
    }

    @Override
    public List<SpuVO> handleExpireVirtualProd() {
        List<SpuVO> spuVOList = spuMapper.getVirtualSpuList();
        if (CollectionUtils.isEmpty(spuVOList)) {
            return null;
        }
        for (SpuVO spuVO : spuVOList) {
            spuVO.setStatus(SpuStatus.OFF_SHELF.value());
            Spu spu = new Spu();
            spu.setSpuId(spuVO.getSpuId());
            spu.setStatus(spuVO.getStatus());
            updateSpu(spu);
        }
        return spuVOList;
    }

    @Override
    public void updateSpuByShopId(Long shopId, Integer sysType) {
        spuMapper.updateSpuByShopId(shopId, sysType);
    }

    @Override
    public List<Map<String, Object>> countByCateIdAndAreaId(Long areaId) {
        //获取一级分类
        List<Map<String, Object>> list = categoryMapper.listPrimaryCategoryId();
        for (int i = 0; i < list.size(); i++) {
            //获取三级分类
            List<Long> listThreeCate = categoryMapper.listCategoryId(Long.valueOf(list.get(i).get("category_id").toString()));
            Long num = spuMapper.countByCateId(listThreeCate);
            list.get(i).put("num", num);
        }
        return list;
    }

    @Override
    public List<Map<String, Object>> countByShop() {
        List<Map<String, Object>> list = spuMapper.countByShopId();
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = list.get(i);
            map.put("shopName", shopDetailFeignClient.getShopDetailByShopId(Long.valueOf(map.get("shop_id").toString())).getData().getShopName());
        }
        return list;
    }
}

